Understanding Polymorphic association in rails

Polymorphic associations are little tricky to understand and many get confused on how to use them and how they are different from other association. We shall get even more vivid picture about polymorphic associations in this article.

With polymorphic associations, a model can belong to more than one other model, on a single association. Let’s take an example.

Say we can comment either on the photo or the event. So let’s have models Event, Photo and Comment. So now, Comment model need to belong to both Event and Photo models on a single association. The association would look like the below:

class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true
end

class Photo < ApplicationRecord
  has_many :comments, as: :commentable
end

class Event < ApplicationRecord
  has_many :comments, as: :commentable
end

The migration for above association would have commentable_id as foreign key and commentable_type on the Comment table.

class CreateComments < ActiveRecord::Migration
  def change
    create_table :comments do |t|
      t.string :content
      t.integer :commentable_id
      t.string :commentable_type

      t.timestamps
    end
  end
end

A polymorphic belongs_to declaration is setting up an interface that any other model can use. From an instance of the Phoyo model, you can retrieve a collection of comments: @photo.comments

Similarly, you can retrieve @event.comments

If you have an instance of the Comment model, you can get to its parent via @comment.commentable.

Loading development environment (Rails 4.1.1)
2.0.0-p247 :001 > photo = Photo.create(name: 'landscape')
2.0.0-p247 :002 > comment = Comment.create(content: 'good landscape picture')
2.0.0-p247 :003 > comment.update(commentable: photo)
=> true
2.0.0-p247 :004 > Photo.first.comments.first.content
 => "good landscape picture"

2.0.0-p247 :005 > event = Event.create(name: 'Cultural fest')
2.0.0-p247 :006 > comment = Comment.create(content: 'samskruthi 2017 rocks')
2.0.0-p247 :007 > comment.update(commentable: event)
=> true
2.0.0-p247 :008 > Event.first.comments.first.content
 => "samskruthi 2017 rocks"

2.0.0-p247 :009 > Comment.last.event.name
=> "Cultural fest"
2.0.0-p247 :0010 > Comment.first.photo.name
=> "landscape"

Leave a Reply

Your email address will not be published. Required fields are marked *