Polymorphic Tables in Ruby on Rails

Rui Freitas
Dec 9, 2019 · 2 min read

A quick overview of ActiveRecord polymorphic associations.

When developing our applications, we often encounter situations where two or more different models have associations that seem to be identical. For instance, we may have a Product and a Service model that have many photos, or a Project, a Contractor, and a Task model that have many comments. One way to approach this problem would be to use one child database table for each parent model:

class Product < ApplicationRecord
has_many :photos, class_name: 'ProductPhotos'
end

Alternatively, we can use ActiveRecord polymorphic associations to store these similar associations in a single database table. According to the Ruby on Rails Guide, polymorphic associations can be defined as follows:

With polymorphic associations, a model can belong to more than one other model, on a single association

We could generate the following models:

rails g model Photo imageable:references{polymorphic}
rails g model Comment commentable:references{polymorphic}

Which creates the following migrations:

class CreatePhotos < ActiveRecord::Migration[5.2]
def change
create_table :photos do |t|
t.references :imageable, polymorphic: true
t.timestamps
end
end
end

And the corresponding ActiveRecord associations would be defined as such:

class Photo < ApplicationRecord
belong_to :imageable
end

Underneath the hood, the polymorphic migration created two columns in each polymorphic table: imageable_id and imageable_type in Photos and commentable_id and commentable_type in Comments. Because a polymorphic table can belong to more than one other model, ActiveRecord uses the polymorphic_type column to determine the class name of the association from to find the correct instance with the polymorphic_id.

In our examples above, imageable_type is a string which can take the value of Product or Service, and imageable_id is a foreign key from one of these two tables, whereas commentable_type is a string which can take the value of Project, Contractor or Task, and commentable_id is a foreign key from one of those three tables.

Light the Fuse and Run

Web development in Ruby on Rails, React, Vue.js and Elixir

Rui Freitas

Written by

Lead Teacher @ Le Wagon | Web Developer @ Light the Fuse and Run: http://lightthefuse.run/ | Photographer @ Rod Loboz: https://blog.rodloboz.com/

Light the Fuse and Run

Web development in Ruby on Rails, React, Vue.js and Elixir

Rui Freitas

Written by

Lead Teacher @ Le Wagon | Web Developer @ Light the Fuse and Run: http://lightthefuse.run/ | Photographer @ Rod Loboz: https://blog.rodloboz.com/

Light the Fuse and Run

Web development in Ruby on Rails, React, Vue.js and Elixir

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store