ActiveRecord models that define a has_many
association often need access to a
specific entry of this list. Think of an user that has many email addresses but
only one that is his primary address. Or a Blog post with many comments of which
one is featured.
How a lot of people do it
A pattern that seems to be quite common is to extend the association by implementing a method that gets you the specific record:
1 2 3 4 5 6 7 |
|
This allows you to access the user’s primary email address via #emails.primary
.
So far so good, but what happens if we need to get a list of users with their
primary email address? Of course we do eager loading to reduce the amount of
database queries:
1 2 3 4 |
|
But when we look at the SQL queries that are actually executed we realize that eager loading is happening but each primary email is queried separately afterwards:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Ouch! This will screw up our app’s performance as the user base grows!
A better way
But there’s another way of picking out one special instance of a has_many
association. A way that also allows eager loading. It’s as simple as defining
just another association pointing to the same object.
1 2 3 4 |
|
Now you can access the user’s primary email address by #primary_email
. Let’s
check the SQL log for a user list using eager loading:
1 2 3 4 |
|
As we can see eager loading is now working properly for the primary email addresses:
1 2 3 4 |
|
Yay! Now all the millions of users out there can sign up on our page without breaking the list of primary email addresses…