Rails: How to handle model subclassing?
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
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
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
.
精彩评论