IS A - What's polymorph
May 4th, 2008
Polymorph is useful because it allows you treat objects of different types uniformly.
NOTE: There is a plugin that saves you from writing the following code, and it also adds extra functionality. See the tutorial has_many_polymorphs for dummies
This article contains some code and irb tests I did when learning about polymorph from these articles.
An Article_Section is made up of various types of content.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
class ArticleSection < ActiveRecord::Base belongs_to :article has_many :article_contents # This code is better than that below and it works # has_many :notes, :through => :article_contents, :source => :contentizable, # :source_type => 'Note' has_many :notes, :through => :article_contents, :source => :note, :conditions => "article_contents.contentizable_type = 'Note'" has_many :links, :through => :article_contents, :source => :link, :conditions => "article_contents.contentizable_type = 'Link'" def contentizables self.notes + self.links end end |
Content can be placed in many articles.
Content can be of various type i.e. text, code, url's
1 2 3 4 5 6 7 8 9 10 11 12 |
class ArticleContent < ActiveRecord::Base belongs_to :article_sections belongs_to :contentizable, :polymorphic => true # This code is better than that below and works. # has_many :notes, :as => :contentizable belongs_to :note, :class_name => "Note", :foreign_key => "contentizable_id" belongs_to :link, :class_name => "Link", :foreign_key => "contentizable_id" end |
Note Object is of type Content
1 2 3 4 5 |
class Note < ActiveRecord::Base has_many :article_contents, :as => :contentizable has_many :article_sections, :through => :article_contents end |
Link object is of type Content
1 2 3 4 5 |
class Link < ActiveRecord::Base has_many :article_contents, :as => :contentizable has_many :article_sections, :through => :article_contents end |
Testing using the irb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
>> a = Article.create(:title => "a1") => #<Article id: 12, title: "a1", published_at: nil, author: nil, keywords: nil, state: nil, created_at: "2008-05-01 18:07:41", updated_at: "2008-05-01 18:07:41"> >> as = ArticleSection.create(:article_id => a.id ) => #<ArticleSection id: 11, article_id: 12, content_id: nil, content_type: nil, order: nil, created_at: "2008-05-01 18:07:44", updated_at: "2008-05-01 18:07:44"> >> as.notes => [] >> as.links => [] >> l = Link.create(:url => "some.domain.com") => #<Link id: 3, content_id: nil, url: "some.domain.com", description: nil, title: nil, contentizable_id: nil, contentizable_type: nil, created_at: "2008-05-01 18:08:20", updated_at: "2008-05-01 18:08:20"> >> as.links << l => [#<Link id: 3, content_id: nil, url: "some.domain.com", description: nil, title: nil, contentizable_id: nil, contentizable_type: nil, created_at: "2008-05-01 18:08:20", updated_at: "2008-05-01 18:08:20">] >> n = Note.create(:description => "hi", :title => "something") => #<Note id: 9, description: "hi", contentizable_id: nil, contentizable_type: nil, created_at: "2008-05-01 18:08:41", updated_at: "2008-05-01 18:08:41", title: "something", content_id: nil> >> as.notes << n => [#<Note id: 9, description: "hi", contentizable_id: nil, contentizable_type: nil, created_at: "2008-05-01 18:08:41", updated_at: "2008-05-01 18:08:41", title: "something", content_id: nil>] >> as.article_contents => [#<ArticleContent id: 1, article_section_id: 11, contentizable_id: 3, contentizable_type: nil, created_at: "2008-05-01 18:08:25", updated_at: "2008-05-01 18:08:25">, #<ArticleContent id: 2, article_section_id: 11, contentizable_id: 9, contentizable_type: nil, created_at: "2008-05-01 18:08:49", updated_at: "2008-05-01 18:08:49">] >> as.article_contents.length => 2 |
Another test using the irb
1 2 3 4 5 6 7 |
>> n = Note.create(:title => "t", :description => "d") => #<Note id: 14, description: "d", contentizable_id: nil, contentizable_type: nil, created_at: "2008-05-01 19:08:46", updated_at: "2008-05-01 19:08:46", title: "t", content_id: nil> >> as.notes << n => [#<Note id: 12, description: "d", contentizable_id: nil, contentizable_type: nil, created_at: "2008-05-01 19:07:51", updated_at: "2008-05-01 19:07:51", title: "t", content_id: nil>, #<Note id: 13, description: "d", contentizable_id: nil, contentizable_type: nil, created_at: "2008-05-01 19:08:06", updated_at: "2008-05-01 19:08:06", title: "t", content_id: nil>, #<Note id: 14, description: "d", contentizable_id: nil, contentizable_type: nil, created_at: "2008-05-01 19:08:46", updated_at: "2008-05-01 19:08:46", title: "t", content_id: nil>] >> n.article_contents => [#<ArticleContent id: 6, article_section_id: 21, contentizable_id: 14, contentizable_type: "Note", created_at: "2008-05-01 19:08:50", updated_at: "2008-05-01 19:08:50">] |
Leave a Reply