Reputation: 1255
There are ten ways to do anything but what is the best practice approach to organizing the Document
and Section
models described below in Rails?
Documents can have n number of sections. Each Section
can be a specialized type of section with its own attributes and associations differing from other sections. And each Document
needs to track a section order state for all of the sections associated with it regardless of type.
I could create model classes for each Section
type and associate them on Document
as has_many SectionTypeA
, has_many SectionTypeA
and write a sorting mechanism to put together a sorted collection of all types for the given document.
I looked into Single Table Inheritance. But the STI approach seems questionable when the specialized attributes are more complicated than a few string or integer fields. Sections will have attributes that map to database text columns and their own section has_many, has_one associations.
Here's a rough outline of the elements described:
Document
Sections
-Section Type A
Title, freeform text
-Section Type B
Title, collection of urls
-Section Type C
Title, collection of images with title and collection of image comments
Upvotes: 1
Views: 1325
Reputation: 423
This seems like it could be solved with a reverse polymorphic association like:
# Models
class Document < ActiveRecord::Base
has_many :document_sections
has_many :freeform_sections,
:through => :document_sections,
:source => :section,
:source_type => 'FreeformSection'
def add_section(section)
self.freeform_sections << section if section.is_a? FreeformSection
end
end
class DocumentSection < ActiveRecord::Base
belongs_to :document
belongs_to :section, :polymorphic => true
end
class FreeformSection < ActiveRecord::Base
has_one :document_section, :as => :section
has_one :document, :through => :document_section
end
# Migrations
class CreateDocuments < ActiveRecord::Migration
def change
create_table :documents do |t|
t.string :name
t.timestamps
end
end
end
class CreateDocumentSections < ActiveRecord::Migration
def change
create_table :document_sections do |t|
t.integer :section_id
t.string :section_type
t.references :document
t.timestamps
end
end
end
class CreateFreeformSections < ActiveRecord::Migration
def change
create_table :freeform_sections do |t|
t.references :section
t.timestamps
end
end
end
# Usage
document = Document.create :name => 'My Doc'
document.freeform_sections << FreeformSection.new
document.add_section FreeformSection.new
document.document_sections
document.freeform_sections
Upvotes: 3
Reputation: 4398
Take a look at polymorphic associations. Maybe you can create a 'sectionable' type for your different Section
types and put those in one polymorphic association in Document
.
Upvotes: 0