Polymorphic Associations in Rails

ruby, rails, activerecord,

Swapnil Gourshete Swapnil Gourshete Follow Jun 19, 2023 · 2 mins read
Polymorphic Associations in Rails

.

What is the usecase?

Suppose two models can be associated to a third model with a common attribute. For example, Image can belong to User as well as Product, because user will have self image and product will have descriptive images of product. This can be achieved with Polymorphic associations - Two or more models can be associated to third model using single association.

How to use it?

Let’s understand how to use it. There are two parts -

  1. Migration defining two fields on the model which will have work as base model. It will have association_id -> int and association_type -> string.
  2. Defining associations in models.

And we are ready to use it.

Lets understand through code example.

Code Example

Suppose we have three models - Picture, User, Product. We need specify polymorphic association at pictures table creation

1. Migration

We will add two fields imageable_type and imageable_id. class-inheritance-example

2. Model associations changes

class-inheritance-example

What if we do not use Polymorphic?

We will have to create two tables representing User-Image and Product-Image associations. That will be storing same attributes in two tables except user_id and product_id.

Benefits

The setup provides easy access to associated models.

  • From an instance of the User model, you can retrieve a collection of pictures: @user.pictures
  • Similarly, you can retrieve @product.pictures
  • If you have an instance of the Picture model, you can get to its parent via @picture.imageable
  • Polymorphic association helps in making your code DRY(Do not Repeat Yourself)

Can we test polymorphic associations?

Yes, of course. I am using rspec for unit testing instead of minitest. It can be installed from here install rails rspec.

If you had not installed rspec previously, run

$ rails generate rspec:model user
      create  spec/models/user_spec.rb

$ rails generate rspec:model product
      create  spec/models/product_spec.rb

$ rails generate rspec:model picture
      create  spec/models/picture_spec.rb

Now we have empty rspec files for models. Let’s add following code to picture model rspec file polymorphic-rspec-example

And when we run this spec file polymorphic-rspec-example

It will pass with flying colors!



References -


Swapnil Gourshete
Written by Swapnil Gourshete Follow
Hi I am Swapnil, a Software Engineer and computer science enthusiastic