Polymorphic associations In Ruby on Rails

Efficiently Modeling Relationships Across Diverse Entities with Polymorphic Associations in Ruby on Rails

Patrick Karsh
3 min readApr 2, 2023

What is a polymorphic association?

A polymorphic association is a design pattern used in object-relational mapping (ORM) and database schema design to enable a model or table to be associated with multiple other types of models or tables. It provides a flexible and reusable way to model relationships between different entities in a database.

In the context of databases, a polymorphic association involves creating a single table with columns that can store information about the relationships between multiple entities. This table usually includes a reference to the related record (foreign key), as well as a column indicating the type of entity being referenced (e.g., ‘commentable_type’).

In the context of an ORM, such as Ruby on Rails’ ActiveRecord, a polymorphic association allows a single model to be associated with multiple other models without the need for creating multiple join tables or foreign key columns. This is achieved by specifying the association as ‘polymorphic’ in the model definition and including the type information when saving or querying the relationship.

An example of a polymorphic association could be a “Comment” model that can be associated with various entities, like “Posts” or “Images”. Instead of creating separate tables or columns for each relationship, you could create a single “comments” table that would store the foreign key and entity type for each association. This approach allows for greater flexibility and easier maintenance, as you can add new types of entities that can have comments without altering the existing schema or model definitions.

How do you create a polymorphic association in Rails 7

To implement a polymorphic association in Rails 7, you can follow these steps

Create the migration for the polymorphic association

First, create a migration that adds the necessary columns for the polymorphic association. In this example, we’ll use a “Comment” model associated with “Post” and “Image” models.

Generate a migration for the “comments” table:

rails generate migration CreateComments

Edit the generated migration file (e.g., db/migrate/XXXXXXXXXXXX_create_comments.rb) to include the foreign key and entity type columns:

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

t.timestamps
end
end
end

Run the migration

rails db:migrate

Create the associated models

Create the “Comment” model

# app/models/comment.rb
class Comment < ApplicationRecord
belongs_to :commentable, polymorphic: true
end

Update the “Post” and “Image” models to include the polymorphic relationship:

# app/models/post.rb
class Post < ApplicationRecord
has_many :comments, as: :commentable
end

# app/models/image.rb
class Image < ApplicationRecord
has_many :comments, as: :commentable
end

Use the polymorphic association in your controllers and views

Now, you can use the polymorphic association in your controllers and views. For example, when creating a new comment for a post, you can do:

# app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def create
@commentable = find_commentable
@comment = @commentable.comments.build(comment_params)
if @comment.save
redirect_to @commentable, notice: 'Comment was successfully created.'
else
render :new
end
end

private

def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end

def comment_params
params.require(:comment).permit(:content)
end
end

And in your views, you can display comments for both “Post” and “Image” models:

<!-- app/views/posts/show.html.erb -->
<h2>Comments</h2>
<%= render partial: 'comments/comment', collection: @post.comments %>

<!-- app/views/images/show.html.erb -->
<h2>Comments</h2>
<%= render partial: 'comments/comment', collection: @image.comments %>

Now you have implemented a polymorphic association in Rails 7 that allows the “Comment” model to be associated with both “Post” and “Image” models.

--

--

Patrick Karsh
Patrick Karsh

Written by Patrick Karsh

NYC-based Ruby on Rails and Javascript Engineer leveraging AI to explore Engineering. https://linktr.ee/patrickkarsh

No responses yet