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 Teacher
and Student
model, let me first recreate the models I was working with at the time.
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 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.
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
.
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
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
andTeacher
respectively. 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 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!
Please refer to my GitHub repo for the sample used in this guide.
Thanks for reading!
☞ Ruby on Rails Tutorial for Beginners
☞ Ruby on Rails 5 Tutorial: Build Web Application
☞ Top 4 Programming Languages to Learn In 2019
☞ Introduction to Functional Programming in Python
☞ Dart Programming Tutorial - Full Course
☞ Complete Introduction to Ruby on Rails In 60 Minutes | OdinSchool