0
0
RailsHow-ToBeginner · 4 min read

How to Use Polymorphic Association in Ruby on Rails

In Ruby on Rails, use belongs_to :association_name, polymorphic: true in the model that belongs to multiple other models, and has_many :association_name, as: :association_name in the models that can be associated. This setup allows one model to belong to more than one other model on a single association.
📐

Syntax

Polymorphic associations use two key parts: a belongs_to with polymorphic: true in the child model, and a has_many or has_one with as: :association_name in the parent models.

  • Child model: stores association_name_id and association_name_type columns to track which parent it belongs to.
  • Parent models: declare has_many or has_one with as: option to link back.
ruby
class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true
end

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

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

Example

This example shows a Comment model that can belong to either a Post or a Photo. You can create comments for both posts and photos using the same association.

ruby
class CreatePolymorphicExample < ActiveRecord::Migration[7.0]
  def change
    create_table :posts do |t|
      t.string :title
      t.timestamps
    end

    create_table :photos do |t|
      t.string :name
      t.timestamps
    end

    create_table :comments do |t|
      t.text :body
      t.references :commentable, polymorphic: true, null: false
      t.timestamps
    end
  end
end

# Usage in Rails console
post = Post.create(title: 'My Post')
photo = Photo.create(name: 'My Photo')

post.comments.create(body: 'Great post!')
photo.comments.create(body: 'Nice photo!')

post.comments.first.body # => "Great post!"
photo.comments.first.body # => "Nice photo!"
Output
=> "Great post!" => "Nice photo!"
⚠️

Common Pitfalls

Common mistakes include:

  • Not adding both _id and _type columns in the polymorphic table.
  • Forgetting to specify polymorphic: true in the belongs_to association.
  • Using incorrect as: option name in the parent models.
  • Trying to use polymorphic associations with has_one without careful design.
ruby
class Comment < ApplicationRecord
  # Wrong: missing polymorphic: true
  belongs_to :commentable
end

# Correct:
class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true
end
📊

Quick Reference

ConceptUsageNotes
Child model associationbelongs_to :association_name, polymorphic: trueRequires *_id and *_type columns in DB
Parent model associationhas_many :association_name, as: :association_nameLinks back to child polymorphically
Migration columnst.references :association_name, polymorphic: trueCreates *_id and *_type columns
Usagechild = ChildModel.new; parent.comments << childWorks for multiple parent types

Key Takeaways

Use belongs_to with polymorphic: true in the child model to enable polymorphic association.
Parent models must declare has_many or has_one with as: option matching the child association name.
Migration must include both *_id and *_type columns for the polymorphic reference.
Polymorphic associations allow one model to belong to multiple other models through a single interface.
Always double-check association names and migration columns to avoid common errors.