Note: If you are clear with the concept of polymorphic association then you should read this article.
There is one drawback with polymorphic association which you might have faced while creating associations between models . The drawback is that activerecord allows only polymorphic ends to query the association. Lets say we have the following scenario.
Models we have
we can find courses which teacher and student has taken up
The above two statements works perfectly fine.
But what if we want to know all teachers or students who have taken up a particular course. Let say we query
The above two statements would throw error.
Lets see the course_memberships table
When we execute Course.first.teachers, ActiveRecord searches for teacher association in the CourseMembership model but it belongs_to :takable, not :teacher. Hence ActiveRecord throws error.
This can be solved through multiple solutions.
Solution 1:
Here is simple hack for this.
Now the non-polymorphic end query would work i.e. Course.first.teachers and Course.first.students. I just added a teacher and student association in CourseMembership and a condition in Course model.
Solution 2:
We can also solve this problem by defining teachers and students method in Course model but in this case we need to query N+ 1 times to get the result which would lower the performance.
N: number of teachers or students
Solution 3:
we can use includes method, its pretty cool as it takes the whole wad of data at one go from the database and eliminates N+1 query problem.
Here we are using secong degree association, hence we need to pass an hash with array as the value.
The slight problem with this solution is the query end up returning a lot of data to be converted into ActiveRecord objects. Also if there are lot of rows in parent table, preloading will consume a lot of server memory.
There is one drawback with polymorphic association which you might have faced while creating associations between models . The drawback is that activerecord allows only polymorphic ends to query the association. Lets say we have the following scenario.
Models we have
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Teacher | |
has_many :course_memberships, :as => :takeable | |
has_many :courses, :through => :course_memberships | |
end | |
class Student | |
has_many :course_memberships, :as => :takable | |
has_many :courses, :through => :course_memberships | |
end | |
class CourseMembership | |
belongs_to :course | |
belongs_to :takable, :polymorphic => true | |
end | |
class Course #note this model is not the polymorhic end | |
has_many :course_memberships | |
has_many :teachers, :through => :course_memberships | |
has_many :students, :through => :course_memberships | |
end |
we can find courses which teacher and student has taken up
The above two statements works perfectly fine.
But what if we want to know all teachers or students who have taken up a particular course. Let say we query
The above two statements would throw error.
Lets see the course_memberships table
When we execute Course.first.teachers, ActiveRecord searches for teacher association in the CourseMembership model but it belongs_to :takable, not :teacher. Hence ActiveRecord throws error.
This can be solved through multiple solutions.
Solution 1:
Here is simple hack for this.
Now the non-polymorphic end query would work i.e. Course.first.teachers and Course.first.students. I just added a teacher and student association in CourseMembership and a condition in Course model.
Solution 2:
We can also solve this problem by defining teachers and students method in Course model but in this case we need to query N+ 1 times to get the result which would lower the performance.
N: number of teachers or students
Solution 3:
we can use includes method, its pretty cool as it takes the whole wad of data at one go from the database and eliminates N+1 query problem.
Here we are using secong degree association, hence we need to pass an hash with array as the value.
The slight problem with this solution is the query end up returning a lot of data to be converted into ActiveRecord objects. Also if there are lot of rows in parent table, preloading will consume a lot of server memory.
No comments:
Post a Comment