Polymorphic Association

A Polymorphic Association in Ruby on Rails allows a model to be associated with multiple model types through a single relationship.

Table of Contents

What is a Polymorphic Association in Ruby on Rails?

A polymorphic association is a special type of Active Record association where one model can be associated with multiple other models through a single interface.

Instead of creating separate foreign keys and associations for each related model, Rails stores two columns:

  1. *_id – the ID of the associated record
  2. *_type – the class name of the associated model

This allows one model to reference different models dynamically. A common example is a Comment model that can belong to either a Post or a Photo. In short, polymorphic associations let a single model relate to multiple model types in a flexible way.

Why are Polymorphic Associations Useful?

Without polymorphic associations, developers would need separate tables or multiple foreign keys for each relationship type.

  • Polymorphic associations are useful because they:
  • Reduce database complexity
  • Eliminate duplicate association logic
  • Make models more flexible and reusable
  • Simplify handling shared behaviors across different models
  • Keep the schema cleaner when many models share a relationship

They are especially helpful for features like comments, attachments, likes, or activity logs that can belong to many different models.

How Polymorphic Associations Work?

Rails uses a combination of an ID column and a type column to identify the associated record.

Key components:

  • belongs_to :commentable, polymorphic: true – defines the polymorphic side on the child model
  • has_many :comments, as: :commentable – defines the association on the parent model side
  • *_id and *_type columns– store the association details
  • Active Record automatically resolves the correct model at runtime

Example

Scenario 1: A comment that can belong to posts or photos Migration for the comments table:

class CreateComments < ActiveRecord::Migration[7.0] 
  def change 
  def change 
    create_table :comments do |t| 
      t.text :body 
      t.references :commentable, polymorphic: true, null: false 
      t.timestamps 
    end 
  end 
end 

This creates both commentable_id and commentable_type columns in the comments table.

Comment model (app/models/comment.rb):

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

Post model (app/models/post.rb):

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

Photo model (app/models/photo.rb):

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

Creating comments:

post = Post.create(title: "Rails Guide") 
post.comments.create(body: "Great post!") 
photo = Photo.create(title: "Sunset") 
photo.comments.create(body: "Beautiful photo!") 

The same comments table stores comments for both posts and photos using the commentable_type column to differentiate them.

Scenario 2: Accessing the associated record

comment = Comment.first 
comment.commentable
 => Returns the associated Post or Photo object automatically

Rails reads the commentable_type column and automatically returns the correct associated object, whether it is a Post or a Photo.

Where to Use Polymorphic Associations?

  • Comments on different content types
  • File attachments or uploads
  • Likes, reactions, or favorites
  • Activity feeds and notifications
  • Tagging systems
  • Any feature shared across multiple models

In Summary

Polymorphic Associations allow a Rails model to be associated with multiple model types through a single relationship. By storing both the record ID and model type, Rails provides a flexible and reusable way to manage shared relationships across different models.