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_idandassociation_name_typecolumns to track which parent it belongs to. - Parent models: declare
has_manyorhas_onewithas: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
_idand_typecolumns in the polymorphic table. - Forgetting to specify
polymorphic: truein thebelongs_toassociation. - Using incorrect
as:option name in the parent models. - Trying to use polymorphic associations with
has_onewithout 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
| Concept | Usage | Notes |
|---|---|---|
| Child model association | belongs_to :association_name, polymorphic: true | Requires *_id and *_type columns in DB |
| Parent model association | has_many :association_name, as: :association_name | Links back to child polymorphically |
| Migration columns | t.references :association_name, polymorphic: true | Creates *_id and *_type columns |
| Usage | child = ChildModel.new; parent.comments << child | Works 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.