How to Structure Multiple Levels of Hierarchy in Ruby on Rails?
architecture, database-design, ruby-on-rails, ruby-on-rails-3
Solution
It really depends on how far you want to go. If it's just one extra level of hierarchy, then definitely go with the new model. If you're looking to be able to go 2+ levels deep, definitely go with the option of reusing sections.
Problem
A rails app contains many different Pages of content. The Pages are organized into small groups known as Sections: ``` 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 ``` The Sections need to be organized too, but what is the best way to do this - re-use sections themselves, or create a new Unit model? Option 1 - Re-use Section Allow Section to have children and parent Sections. That way, you don't need to create another model with similar fields as Section. Some sections will have_many pages, and other sections will have_many children sections: ``` 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 ``` Option 2 - new Unit model Create another model called Unit to organize the sections. It will have many similar fields to section, but it will be a clearly separate entity. ``` 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 ``` The advantage of Option 1 is it avoid some duplication, and could be adapted in the future if even more levels are needed. However, Option 2 clearly separates the roles of Sections, which have_many pages, from Units, which have_many Sections, which can help keep other code clear. Which is the best approach? Update It seems Option 2 would have clearer code, such as when going through all the Sections. Is it worth re-using Sections if it would make some code more complicated? For example, here's how to list all the Sections in an organized manner: Option 2 - For each Unit, list all the child sections. Then list any Sections that aren't in any Unit. Option 1 - For each parent Section, list all the children Sections. Then list any Section that has with no parent Section or child Section.