To Interface or Not?: Creating a polymorphic model relationship in Ruby on Rails dynamically..
- by Globalkeith
Please bear with me for a moment as I try to explain exactly what I would like to achieve.
In my Ruby on Rails application I have a model called Page.
It represents a web page.
I would like to enable the user to arbitrarily attach components to the page. Some examples of "components" would be Picture, PictureCollection, Video, VideoCollection, Background, Audio, Form, Comments.
Currently I have a direct relationship between Page and Picture like this:
class Page < ActiveRecord::Base
has_many :pictures, :as => :imageable, :dependent => :destroy
end
class Picture < ActiveRecord::Base
belongs_to :imageable, :polymorphic => true
end
This relationship enables the user to associate an arbitrary number of Pictures to the page. Now if I want to provide multiple collections i would need an additional model:
class PictureCollection < ActiveRecord::Base
belongs_to :collectionable, :polymorphic => true
has_many :pictures, :as => :imageable, :dependent => :destroy
end
And alter Page to reference the new model:
class Page < ActiveRecord::Base
has_many :picture_collections, :as => :collectionable, :dependent => :destroy
end
Now it would be possible for the user to add any number of image collections to the page.
However this is still very static in term of the :picture_collections reference in the Page model. If I add another "component", for example :video_collections, I would need to declare another reference in page for that component type.
So my question is this:
Do I need to add a new reference for each component type, or is there some other way? In Actionscript/Java I would declare an interface Component and make all components implement that interface, then I could just have a single attribute :components which contains all of the dynamically associated model objects.
This is Rails, and I'm sure there is a great way to achieve this, but its a tricky one to Google. Perhaps you good people have some wise suggestions. Thanks in advance for taking the time to read and answer this.