2 votes

Persistance de l'implémentation d'un modèle composite - ruby on rails

Quelqu'un a-t-il un bon exemple de bout en bout de la façon de faire persister dans la base de données un modèle composite de GoF tel que celui ci-dessous ?

Classe de base du composant :

class Task
  attr_reader :name

  def initialize(name)
    @name = name
  end

  def get_time_required
    0.0
  end
end

La classe composite :

class CompositeTask < Task
  def initialize(name)
    super(name)
    @sub_tasks = []
  end

  def add_sub_task(task)
    @sub_tasks << task
  end

  def remove_sub_task(task)
    @sub_tasks.delete(task)
  end

  def get_time_required
    time = 0.0 
    @sub_tasks.each { |task| time += task.get_time_required }
    time
  end
end

1voto

tramuntanal Points 31

Avec presque un an de retard, mais je pense qu'il est toujours utile de prolonger ma réponse. Vous aurez besoin d'un ID pour chaque tâche, supposons que cet ID soit le nom de la tâche. Ensuite, avec un nouvel attribut parent dans la tâche, vous serez en mesure de persister l'arborescence pour le composite :

class Task
  attr_reader :name
  attr_reader :parent

  def initialize(name, parent=nil)
    @name = name
    = parent
  end

  def get_time_required
    0.0
  end
end

De cette façon, vous pourrez naviguer du parent vers ses enfants. select * from tasks where parent_id = ? ou d'un enfant à son parent select * from tasks where id = ? .

Une autre astuce consiste à utiliser l'indexation, comme dans les chapitres, pour retrouver toute la hiérarchie sous un nœud donné. Si vous avez un tree_code classé, alors vous pouvez persister de cette façon :

  • Le nœud racine aura 0 tree_code ,
  • Les enfants de Root auront 1, 2, 3,... tree_code (il s'agit de la première génération)
  • deuxième génération pour le nœud avec tree_code 1 aura 1.1, 1.2,... tree_code . Pour le nœud avec tree_code 2 aura 2.1, 2.2,... tree_code
  • etc.

alors vous serez en mesure de récupérer tous les sous-nœuds de la tâche 1 en interrogeant select * from tasks where tree_code like '1.%' .

Il s'agit toujours d'un compromis en termes de performances entre l'insertion/la mise à jour et la sélection, car vous devrez calculer le paramètre tree_code avant de faire persister un composant.

Si vous êtes dans le contexte d'une application Rails, vous pouvez toujours utiliser ascendance

0voto

EJ2015 Points 2379

Vous n'avez besoin que de faire persister les attributs dans db, tels que name y time (vous voudrez probablement le faire persister plutôt que de l'attribuer au moment de l'exécution) et sub_tasks . Et vous ne le faites que pour les tâches liées aux feuilles. En général, vous ne persistez pas chaque tâche composite dans la base de données.

Vous pouvez utiliser STI (single table inheritance) pour réaliser ce modèle. Vous pouvez créer une classe de base Task < ActiveRecord::Base (en supposant que Rails4). Ensuite, vous sous-classez une LeafTask et un CompositTask à partir de cela. Vous pouvez ensuite faire persister chaque tâche que vous avez en tant qu'instance de l'une ou l'autre. Si vos tâches nécessitent des interfaces très différentes, il est préférable de sous-classer chacune d'entre elles. Si chacune d'entre elles requiert même des attributs très différents, vous pouvez envisager un héritage multitable (c'est-à-dire qu'elles se sous-classent toujours à partir de Task mais ils utilisent leurs propres tables).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X