Writing Migrations for Polymorphic Associations in Ruby on Rails
When you want to create an association between a model and 2 or more other models, you need to create a polymorphic association.
Instead of a traditional association where an Image might belong to a Profile (shown below), a polymorphic association would allow images to belong to Profile, Blog Posts, and anything else that needs an image.
class Image < ApplicationRecord belongs_to :profile end class Profile < ApplicationRecord has_many :images end
To make this reference polymorphic, just a few changes are needed:
class Image < ApplicationRecord belongs_to :imageable, polymorphic: true end class Profile < ApplicationRecord has_many :images, as: :imageable end
We make the
belongs_to call with a reference to
:imageable since our Image will belong to multiple models. And instead of storing separate ids, like
profile_id to point to profiles and
blog_post_id to point to a blog post, we combine the ids into a shared id we call
To determine which table this id refers to, we also store a
imageable_type that tells us the name of the model.
Writing Polymorphic Association Migrations
When we want to create a polymorphic table, we need to change a few things in our migrations.
Using the example above, our Image model can belong to either a Profile or a BlogPost. Instead of storing a
blog_post_id we store an id that can point to either called
imageable_id. In order to determine which id the model points to we reference the
As illustrated above, we need 2 fields to make a polymorphic association:
- id of the associated model
- type of the model
Creating a Table With a Polymorphic Association
When we create a table we can either manually create these columns or use a shorthand helper method.
The manual approach would look like this and clearly lay out the columns we want:
class CreateImages < ActiveRecord::Migration[6.0] def change create_table :images do |t| t.bigint :imageable_id t.string :imageable_type end add_index :images, [:imageable_type, :imageable_id] end end
Or we can use the shorthand
references method. It doesn't explicitly show us all the columns being created but it's a little easier to work with.
class CreateImages < ActiveRecord::Migration[6.0] def change create_table :images do |t| t.references :imageable, polymorphic: true end end end
Both approaches will result in the same change to your database.
Adding a Polymorphic Column to an Existing Table
You can use the
add_reference method If you already created the table and just need to add a column,
Here's what it would look like:
class AddImageableToImages < ActiveRecord::Migration def change add_reference :images, :imageable, polymorphic: true, index: true end end
This will do the same as all the other variants above, creating