Polymorphic Associations in Rails

Polymorphic Associations in Rails

  • 435

Polymorphic Associations in Rails .A while back, while working on a project, I decided to have separate models/tables for teachers and students as opposed to having one user model. At the time, having two models worked best for the structure of my application.

A while back, while working on a project, I decided to have separate models/tables for teachers and students as opposed to having one user model. At the time, having two models worked best for the structure of my application.

But at some point, I did come across a minor problem. When I asked for guidance, I was pointed to the solution of polymorphic association. Of course, I didn’t know what it was initially.

I did some research to determine how it worked and applied it to my project and it solved my issue!

In this guide, I will cover the problem I faced during my project and how the concept of polymorphic association solved it. (If you only care about how to implement it, feel free to scroll down to the solution.

The Problem

To understand the problem I faced with having a Teacher and Student model, let me first recreate the models I was working with at the time.

Models

Let’s say we have four models, Teacher, Student, Announcement, and Comment.

An announcement can be created for an online classroom. From that announcement, a thread can be started where teachers and students can add comments on the announcement.

Let’s take a look at how the models will look, drawn out:

Association

Association between Announcement, Comment, Student and Teacher

An Announcement, Teacher, and Student can have many Comments. A Comment belongs to an Announcement, Teacher, and Student.

Wait a minute, there’s something wrong with that logic. A Comment certainly belongs to an Announcement but it cannot belong to a Teacher/Student at the same time.

Only one of them made the comment. Ideally, the comment can only belong to a teacher or a student. This is where polymorphic associations can solve the dilemma.

The Solution (Polymorphic Association)

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

Let’s assume we have the Teacher, Student, and Announcement models all generated. Let’s set up the Comment model. In the terminal:

rails g model Comment content:string announcement_id:integer commentable_id:integer commentable_type:string

Let’s break down the attributes we are generating along with the model. The content represents the string of the Comment and the announcement_id represents the Announcement it is associated with (a comment is associated to one announcement at all times).

The commentable_id represents the foreign_key and commentable_type tells the comment model which model (Teacher/Student) it is associated with.

Let’s run:

rails db:migrate

In the app/models/comment.rb, we add the following associations:

   belongs_to :announcement
   belongs_to :commentable, polymorphic: true
end

With the first association, we have the basic belongs_to announcement. With the second, we are declaring polymorphic association by making Comment belong_to :commentable instead of the Teacher or Student model.

Commentable is not a model in the application, it taking care of polymorphic association. Now, let’s check the association for the other end of the Teacher and Student model.

In the app/models/teacher.rb:

   has_many :comments, as: :commentable
end

In the app/models/student.rb:

   has_many :comments, as: :commentable
end

Both associations are saying that Teacher and Student has_many comments through the polymorphic association, commentable.

Testing the Association

In the db/seeds.rb, let’s create a few instances to test out the associations along with inputting byebug to enter the console.

teacher = Teacher.create(name: "Teacher")
student = Student.create(name: "Student")
byebug
puts 'seeded'

Let’s run:

rails db:seed

Byebug Session

Let’s break down the commands executed in the byebug session. A Comment instance was created with the polymorphic commentable pointing to the Student instance and stored to the variable studentComment.

Similarly, another Comment instance is created with commentable set to the Teacher instance and stored in the variable teacherComment.

By checking each Comment instance’s commentable, we notice that they belong to the instance of Student andTeacherrespectively. Thus, the polymorphic association is established. Comment can belong to more than one model on a single association.

Closing Remarks

The idea of polymorphic association is to establish a model that can belong to more than one other model on a single association.

In my case, this may not have been necessary had I incorporated a single User model instead of Teacher and Student.

But there will be cases where situations like these could arise even if there’s a single model and polymorphic association can be the solution.

We covered the basics and implementation of polymorphic associations. Thank you for reading!

Resources

Please refer to my GitHub repo for the sample used in this guide.

Thanks for reading!