Saturday, July 23, 2011

Rails 3.0 Active Record -- Polymorphic association

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.