Here is a little known feature of ActiveRecord’s Associations that rarely gets mentioned. Even though it has been documented, it rarely makes any news. I love this feature.
Basic Associations
So lets assume I have two models: Student and Assignment, where a Student has many Assignments, and thus the Assignment belongs to the Student.
Lets also assume that the Assignment has a field called ‘state‘, indicating whether it is submitted, finished, hasn’t started, procrastinating, or eaten by the dog.
The general way to find assignments of a particular state is to use the find method with a set of conditions.
The first line, finds all submitted assignments, and the second one, all incomplete assignments.
But it’s tedious to type this up each and every time we want to find this sort of assignments. Also you can make mistakes, and it makes your code very messy.
Extending Associations
So let’s move these finder methods into the association itself. I present to you our new Student class!
And now we can find all submitted assignments and all incomplete assignments like such:
Doesn’t that just feel good?
But if you are like me, you’ll keep adding more and more methods to the extension. Which will start making it once again, messy and difficult to read. Damn
Extending Associations into a Module
So once again we can extract it out, and this time store it into a module.
You can keep this file wherever you like, but just to keep things simple, I suggest leaving the extension in the model’s file.
Note: The extension/module is not specific to the model. If other model’s have the same needs, you can reuse this module.


3 Comments
Nice article again … that was something I didn’t know about. Somewhat related is the use of association proxies. Jamis wrote a nice article on that feature here:
http://therailsway.com/2007/3/26/association-proxies-are-your-friend
Check out your SQL logs, it appears that when extending associations like this, it will, for instance, load all of students.assignments out of the database before the call to .submitted. This is un-good, and detrimental to a technique which is, as you say, quite pretty.
Ignore that last comment, I was doing something funky. My fault, not Rails’. I’ll go back into my box now.