Association Preloading in Rails Edge
Posted by Lance Ivy Thu, 28 Feb 2008 01:30:00 GMT
I try and watch the Rails changesets for anything interesting. About a month ago I saw [8672], an implementation of ticket 9640. This sweet patch (and subsequent bug-fixes, etc.) introduced a new strategy for eager loading associated records from the database. It’s a strategy I started trying to hack for a past client, except done much better.
The basic idea is that instead of creating a monstrous SQL join to eager load all those associations you plan to utilize in your view, ActiveRecord will run the main query and then run follow-up queries to load all the :includes you specified.
There are pros and cons to the strategy, of course. Not the least of which is the fact that sometimes you need those :includes in order to execute your SQL conditions and ordering clauses. The patch fixed this problem by scanning the conditions and order SQL for any references to the associated tables, then falling back to the join strategy if necessary.
Personally, I think you should be able to specify a :preload option apart from the :includes option. But until that gets patched into edge, there’s a dead-simple way to do manual preloading:
class Post < ActiveRecord::Base
# note that preload_associations() is a protected
# method, so either create a custom finder or use
# the send() bypass
def find_with_comments
returning find(:all,
:include => :status,
:conditions => "status.name = 'live'") do |results|
# will run two extra queries to retrieve and load the
# comments for the posts in the result set, then find
# the authors of those comments.
preload_associations(results, {:comments => :authors})
end
end
endThis is a really contrived example, but it shows how you can execute a join (with the :status association) then preload a couple extra associations by hand. Easy-peasy.
Subscribe
Hey Lance ,
Do you happen to know if there is anything like this for Rails 1.2? I find the automatic preloading very useful, as I am having to code this manually right now, but I am not on Rails 2..
Hi Alex, I don’t know of anything like this for Rails 1.2, sorry!