Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 持久化复合模式实现——RubyonRails_Ruby On Rails_Design Patterns_Composite - Fatal编程技术网

Ruby on rails 持久化复合模式实现——RubyonRails

Ruby on rails 持久化复合模式实现——RubyonRails,ruby-on-rails,design-patterns,composite,Ruby On Rails,Design Patterns,Composite,有没有人有一个很好的端到端示例,说明如何将来自GoF的文本书复合模式持久化到数据库中,如下面的一个 组件基类: class Task attr_reader :name def initialize(name) @name = name end def get_time_required 0.0 end end 复合类: class CompositeTask < Task def initialize(name) super(name

有没有人有一个很好的端到端示例,说明如何将来自GoF的文本书复合模式持久化到数据库中,如下面的一个

组件基类:

class Task
  attr_reader :name

  def initialize(name)
    @name = name
  end

  def get_time_required
    0.0
  end
end
复合类:

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
类复合任务@sub_tasks您只需要将属性持久化到db,例如
name
time
(您可能希望持久化它,而不是在运行时分配它)和
sub_tasks
。您只对叶任务执行此操作。您通常不会将每个组合任务都持久化到数据库中


您可以使用STI(单表继承)来实现此模式。您可以创建一个基类
任务
(假设Rails4)。然后,您可以从中为
LeafTask
compositetask
创建子类。然后,您可以将您拥有的每个任务作为其中任何一个任务的实例进行持久化。如果您的任务需要非常不同的接口,那么您可能希望对每个接口进行子类化。如果它们中的每一个都需要非常不同的属性,那么您可以考虑多表继承(即,它们仍然是从<代码>任务> /代码>的子类,但是它们使用它们自己的表)。

迟到一年,但我觉得扩展我的答案仍然有用。每个任务都需要一个ID,假设这个ID是任务的名称。然后,通过任务中的新父属性,您将能够持久化组合的树结构:

class Task
  attr_reader :name
  attr_reader :parent

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

  def get_time_required
    0.0
  end
end
通过这种方式,您将能够从父级导航到其子级
select*from tasks where parent_id=?
或从某个子级导航到其父级
select*from tasks where id=?

另一个技巧是使用索引,就像在章节中一样,检索某个节点下的所有层次结构。如果您有一个
树\u code
字段,则可以通过以下方式保持:

  • 根节点将有0个
    树\u code
  • root的子代将有1,2,3<代码>树\代码
(这些是第一代)
  • 具有
    tree\u code
    1的节点的第二代将具有1.1、1.2、<代码>树\代码
    。对于具有
    树的节点,代码
    2将具有2.1、2.2、<代码>树\代码
  • 等等
  • 然后,您将能够通过查询
    select*从任务中检索任务1的所有子节点,其中树的代码类似于'1.%'

    这始终是插入/更新与选择之间的性能权衡,因为在持久化任何组件之前,您必须计算
    树\u code


    如果您在Rails应用程序的上下文中,您可以随时使用

    谢谢。如何持久化CompositeTask创建的关系?