.
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 -
- Migration defining two fields on the model which will have work as base model. It will have
association_id
->int
andassociation_type
->string
. - 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
.
2. Model associations changes
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
And when we run this spec file
It will pass with flying colors!
References -