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.
To understand the problem I faced with having a
Student model, let me first recreate the models I was working with at the time.
Let’s say we have four models,
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 between Announcement, Comment, Student and Teacher
Student can have many
Comment belongs to an
Wait a minute, there’s something wrong with that logic. A
Comment certainly belongs to an
Announcement but it cannot belong to a
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.
With polymorphic associations, a model can belong to more than one other model, on a single association.
Let’s assume we have the
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).
commentable_id represents the
commentable_type tells the comment model which model (Teacher/Student) it is associated with.
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
belong_to :commentable instead of the
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
has_many :comments, as: :commentable end
has_many :comments, as: :commentable end
Both associations are saying that
has_many comments through the polymorphic association,
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 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
Comment instance is created with
commentable set to the
Teacher instance and stored in the variable
By checking each
commentable, we notice that they belong to the instance of
Teacherrespectively. Thus, the polymorphic association is established.
Comment can belong to more than one model on a single association.
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
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!
Please refer to my GitHub repo for the sample used in this guide.
Thanks for reading!