4

一个rails应用程序包含许多不同的页面内容。页被组织成称为节小团体:如何在Ruby on Rails中构建多层次的层次结构?

class Page < ActiveRecord::Base 
    attr_accessible: section_id #etc.. 
    belongs_to :section 
end 

class Section < ActiveRecord::Base 
    attr_accessible :title #, etc... 
    has_many :pages 
end 

章节需要太有组织的,但什么是做到这一点的最好办法 - 再利用部分本身,或创建一个新的单位模型?

选项1 - 重复使用部分
允许部分有子部分和父部分。这样,您就不需要创建另一个与Section类似的字段。部分路段会have_many页面和其他部分将have_many儿童部分:

class Section < ActiveRecord::Base 
    attr_accessible :parent_id :title # etc... 
    has_many :pages 

    belongs_to :parent, class_name: "Section" 
    has_many :children, class_name: "Section", foreign_key: "parent_id" 
end 

选择2 - 新单位模型
创建一个名为单位组织部分另一种模式。它将有许多类似的领域,但它将是一个明显独立的实体。

class Section < ActiveRecord::Base 
    attr_accessible :title, :unit_id # etc... 
    has_many :pages 
    belongs_to :units 
end 

class Unit < ActiveRecord::Base 
    attr_accessible :title # etc... 
    has_many :sections 
end 

选项1的优点是避免了一些重复,如果需要更多层次,可以在未来进行调整。然而,选项2明确地将具有多个页面的部分的角色与具有多个部分的单元分开,这可以帮助保持其他代码清晰。哪种方法最好?

更新
看来备选方案2将有更清晰的代码,这样通过所有的节会时。是否值得重新使用部分,如果它会使一些代码更复杂?例如,以下是如何以有组织的方式列出所有部分:

选项2 - 对于每个单元,列出所有子部分。然后列出任何不在任何单位的部分。

选项1 - 对于每个父节,列出所有子节。然后列出没有父节或子节的任何节。

+0

部分是否可以出现在不同的页面上?而一个页面只有一个部分?我会认为这是另一种方式:) Ow等待:你不是呈现页面,一个部分有很多页面,但你的父母/容器会例如成为一本书吗?一本书有很多部分,每部分都有很多页面? – nathanvda

+0

@nathanvda,页面是最小的单位,许多页面一起组织成部分。 “单位”可能是一个较大的单位,用于保存各个部分,类似于教科书中的单位。 –

回答

2

这实际上取决于你想走多远。如果它只是一个额外的层次结构,那么一定要使用新的模型。如果你希望能够深入到2+层,绝对可以选择重复使用部分。

0

我会用嵌套的部分去使用awesome_nested_set。通过执行此路线,可以减少获取某个部分及其所有子部分所需的数据库调用次数。 Unit类除了组部分之外没有其他更多的功能,并且它似乎也重复了部分的常见列。 title ...需要注意的另一件事是,如果您的要求包括具有任意深度嵌套部分的能力。使用单元方法,您会陷入1级深度。

0

您不必为所有数据存储使用关系数据库。

Mongodb(mongoid:http://mongoid.org/en/mongoid/index.html)可能是您的问题的一个很好的解决方案。

class Page 
    include Mongoid::Document 

    embeds_many :sections, :class_name => 'Sections', :inverse_of => :page 
end 

class Section 
    include Mongoid::Document 
    field :title, :type => String, :default => '' 

    embedded_in :page, :class_name => 'Page', :inverse_of => :sections 
end 
3

如果您看到Section和它的子节点具有完全相同的方法,那么值得重用Section(使用Option 1)。否则,你应该去选择2

关于你对如何列出有组织地所有部分的关注:

选项1 - 这是不是也这样做,除非你想要遍历通过一个具有父节和子节的集合。看看我们如何能够在下面做一些查询的ActiveRecord的:

sections_with_parent = Section.joins(:parent) 
sections_with_children = Section.joins(:children).uniq 
parent_key_with_children_values = Section.joins(:children).uniq.inject({}) do |result, section| 
    result.merge({section => section.children}) 
end 
sections_with_no_parent = Section.where(parent_id: nil) 

选择2 - 下面是比较上面的一些代码:

sections_with_parent = Section.joins(:unit) 
units_with_children = Unit.joins(:sections).uniq 
parent_key_with_children_values = Unit.joins(:sections).uniq.inject({}) do |result, unit| 
    result.merge({unit => unit.sections }) 
end 
sections_with_no_parent = Section.where(unit_id: nil) 

正如你可以看到,这两个选项都会有非常相似的用于列出儿童和父母的代码,因此在决定选择何种选择时不应该担心。

+0

可以遍历视图中的单位和部分: 'Unit.all.each do | unit | <%= unit.name%> unit.sections.each do | section | <%= section.name%> 结束 结束# 我认为这会更迭混淆通过父节和子节时。 –

+0

我明白你的观点。但是,如果在Unit和Section模型中会出现很多重复的行为,那么使用'Section.id(section_id:nil).each do | section |'或'Section.children do | child |'与重复的代码相比,这些视图是最小的。所以这取决于你是否认为Section和Unit模型会有类似的行为。 – Gjaldon