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.
It will be worth reusing Section(using Option 1), if you see Section and its children having exactly the same methods defined in them. Otherwise, you should go for Option 2.
Regarding the concerns you had on how to list all the Sections in an organized manner:
Option 1 - This isn't and can be done unless you want to iterate through one collection which has the parent section and the children sections. See how we could do some of the queries in ActiveRecord below:
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)
Option 2 - Below are some code for comparison with above:
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)
As you can see, both options will have very similar code for listing children and parents so that shouldn't be a concern when deciding on what option to go for.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With