Eager loading objects in a Rails has_many :through association

I’m still working on the Rails application that was the source for [this tutorial](http://www.matthewman.net/articles/2006/01/06/rails-activerecord-goes-through) — which loads of developers who I really respect keep linking to, so I must have done something right there!

Anyway, I’m going to blog this bit of code in the hope that it will help me remember it.

As stated before, I have `Production` and `Venue` objects, which are linked by means of intermediary `Run` objects. Minimal code:

class Production < < ActiveRecord::Base
has_many :runs
has_many :venues, :through => :runs
end

class Venue < ActiveRecord::Base
has_many :runs
has_many :productions, :through => :runs
end

class Run < ActiveRecord::Base
belongs_to :production
belongs_to :venue
end

Now, when listing the productions, I need to display a small amount of information about when and where each production is on. The rules that determine what get displayed vary, and aren't particularly relevant to the discussion here. What matters to me is that, when listing (say) 20 productions, with run and venue information included, all the data is collected in a single SQL query.

As with standard joins, you can use the `find` method's `:include` option to include associated objects within the query. But I wasn't having much luck pulling in both the runs and the venues: the runs would be detected, but iterating through the productions would trigger a fresh SQL query to find the relevant venue information.

Today, I found what I had to do to get it to work. The format for the find needs to be:

@productions = Production.find(:all, ... , :include => {:runs => :venues})

Lo and behold, all the requisite data is collected in a single query, which substantially cuts down on the page load time on my development box.

I’m not quite sure why the hash works — or, to be honest, how I stumbled upon the solution: I’ve been scouring the internet all day, yet for some reason I can’t find the page in my browser history. All I know is that it’s not an approach I’d have stumbled upon myself, as it’s not necessarily as intuitive as most ActiveRecord code is. However, there is a certain elegance to it, with the hash’s arrow symbolising the relationship from one object type to the next, which should hopefully enable me to remember the construction in future.

2 thoughts on “Eager loading objects in a Rails has_many :through association”

  1. Thanks for sharing! I had exactly the same problem and I tried your hash thing in my :include and it worked! Really tricky concept to understand, specially when I was browsing articles and tutorials and didn't really find anything explaining the hash use in :include, only superficial things. Thanks!!