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:
- *_id – the ID of the associated record
- *_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.