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 imageable_id.
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 profile_id or 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 imageable_type.
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 imageable_id and imageable_type fields.