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