eager_record
eager_record copied to clipboard
Extend ActiveRecord to eagerly preload associations on a result set when one association is accessed
= EagerRecord
Never pass the :include
option to find
again.
EagerRecord is a simple extension to ActiveRecord that automates the process of preloading associations in a result set. Each time ActiveRecord loads a collection of more than one record out of the database, a reference to the collection is stored in each record. Then, when you first access an association on one of those records; EagerRecord automatically preloads that association for all of the records in the collection.
== Basic Usage
There isn't really any usage; just install the gem and add it as a dependency. Whereas before you might write:
Comment.all(:include => :user).each { |comment| puts comment.user }
Now you get the same effect with:
Comment.all.each { |comment| puts comment.user }
In the first iteration of that loop, all the comments' users are loaded in a single SQL query.
== Scoped Preloading
It isn't enabled by default, but EagerRecord has experimental support for
"scoped preloading". If you turn it on, EagerRecord will perform preloading
on scoped associations in the same way that it does so for normal ones. For
instance, let's say you've got a :ham
named scope for your Comment
class:
Post.all.each { |post| puts post.comments.ham.inspect }
In the first iteration of this loop, EagerRecord will preload all of the ham comments for all of the posts in the collection; the above code will only generate two SQL queries. A couple of caveats:
-
This only works for normal
has_many
associations right now. I could add support for other collection types in the future. -
The code that does this is considerably more invasive in ActiveRecord's internals than the regular eager preloading code. It basically has to trick ActiveRecord into thinking that there is an association collection defined on your model that doesn't actually exist, and then tell it to preload that association. There are a couple of tests; so I know it basically works, but beware that your mileage may vary. Because of this, you have to explicitly tell eager record you want to use this feature (put this line in a file in
config/initializers
:EagerRecord::ScopedPreloading.install
As an alternative to using this functionality, consider defining extra scoped associations with
:readonly => true
as needed.
=== Does it work with all association types?
==== Mostly...
The test suite covers just about all of them; if you find one that doesn't work, please file an issue.
==== Except!
There's a bug in ActiveRecord's preloading that causes it to build an invalid
query when preloading a has_many :through
association that defines a
:conditions
option that references the join table. For that reason,
EagerRecord does not attempt to eagerly load has_many :through
associations
that have a :conditions
option.
=== Do I need to make any changes to my code?
EagerRecord doesn't add any new methods to ActiveRecord, so you don't need to
interact with it directly. However, you might want to make adjustments to your
code to encourage preloading to happen at the earliest possible point. In
particular, if you're using size
or first
or last
, on a collection,
but then later on also working with all the members of that collection, you're
better off calling to_a
at the beginning so that preloading happens and
ActiveRecord doesn't make extra SQL queries.
== This is free software.
The author(s) of this software relinqiush all copyright on it to the maximum extent permitted by law. Anyone is free to copy, distribute, mangle, sell, improve, destroy, heckle, hate, or love this software with no restrictions.