Polymorphic Many-to-Many Associations in Rails
Posted: September 6, 2011 Filed under: rails, ruby 2 Comments »Rails has various Active Record associations that can be defined between models.
First of all why do we need associations between models? Association between models helps us to perform certain common operations very simple and easy in our Rails code.
Basically Rails supports six types of Associations namely:
- belongs_to
- has_one
- has_one :through
- has_many
- has_many :through
- has_and_belongs_to_many
In the above has_many and belongs_to associations are both commonly used Active Record associations in Rails.
Recently I learnt one more association in Rails which is known as Polymorphic association. I found it very interesting and would like to share it.
Polymorphic Association
In polymorphic association a model belong to more than one other model on a single association.
In one of the project which I was working on, I had to implement polymorphic many-to-many association between the models. The implementation of polymorphic many-to-many association in Rails is very simple.
Let me explain about polymorphic many-to-many association with an simple example.
Consider an example application which has two models namely Book and Article. These two models are associated to a common model called Tag. Book and Article has many tags. But a tag can have many books and also a tag can have many articles. In this case we have many-to-many relationship.
The implementation of above scenario will be like below.
First we have the models Book and Article
class Book < ActiveRecord::Base has_many :tags, :through => :taggings has_many :taggings, :through => :taggable end class Article < ActiveRecord::Base has_many :tags, :through => :taggings has_many :taggings, :through => :taggable end
Then we have the Tag model
class Tag < ActiveRecord::Base has_many :books, :through => :taggings, :source => :taggable, :source_type => "Book" has_many :articles, :through => :taggings, :source => :taggable, :source_type => "Article" has_many :taggings end
Finally we have our join model Tagging
class Tagging < ActiveRecord::Base belongs_to :tag belongs_to :taggable, :polymorphic => true end
From the above implementation we can access tags of books and articles as
book.tags article.tags
We can also access the books and articles based on a tag
tag.books tag.articles
We can also get the taggings and taggable of a tag
tag.taggings tag.taggable
In the above example we have join model which has the fields namely name, taggable_id and taggable_type. The taggable_type field defines that to which model the tag is associated.
Finally let me explain how we get books or articles with respect to a tag. In tag model we have defined has_many relations to books and articles. But there are other options mentioned.
The :through option defines through which model we can access the books or articles. In the above example it is taggings.
The :source option tells the Rails to consider the taggable association instead of expecting an association on taggings.
The :source_type specifies the class of type of polymorphic association that we want to retrieve.
The above is an simple example explaining the implementation of polymorphic many-to-many association in Rails. I hope the above article is interesting and useful.
Thanks, this helped me. I had to change:
has_many :taggings, :through => :taggable
to
has_many :taggings, :as => :taggable
Clutch, brother – very very clutch.
I was knee-deep into an app utilizing polymorphic belongs_to before I realized the need for a has_many. This has saved me much trouble.