preload_associations
- 1.0.0
- 1.1.6
- 1.2.6
- 2.0.3
- 2.1.0 (0)
- 2.2.1 (35)
- 2.3.8 (0)
- 3.0.0 (0)
- 3.0.9 (-2)
- 3.1.0
- 3.2.1
- 3.2.8
- 3.2.13
- 4.0.2
- 4.1.8
- 4.2.1
- 4.2.7
- 4.2.9
- 5.0.0.1
- 5.1.7
- 5.2.3
- 6.0.0
- 6.1.3.1
- 6.1.7.7
- 7.0.0
- 7.1.3.2
- 7.1.3.4
- What's this?
preload_associations(records, associations, preload_options={})
protected
Loads the named associations for the activerecord record (or records) given preload_options is passed only one level deep: don’t pass to the child associations when associations is a Hash
preload_associations manually
Usually you preload associations using :include => [ ... ]. In Rails 2.1 each association is fetched with a separate query. Something like:
Post.find(:all, :include => [:tags, :user])
will produce 3 queries - each for posts, tags and users.
But sometimes you have a complex query, which uses :joins => :other_association and conditions between multiple tables, but not the ones you need to include. Then everything is mixed back in one query like in old versions of Rails.
Another case may be when it is not possible to use :include at all, for example while using find_by_sql, but you still want/need to preload associated records.
In rails 2.1 find uses preload_associations internally, when it is possible (There are no joins or conditions between tables).
So then you can preload asociations manually from within your model:
class Post < ActiveRecord::Base
has_many :tags belongs_to :user ... def self.find_complex_with_includes posts = find_by_sql(...) # or find(:all, :joins => .....) preload_associations(posts, [:tags, :user]) posts end
end
and then do
@posts = Post.find_complex_with_includes
Whacky edge case
The above works great as long as you select the primary key of the owning assocations.
preload_associations calls a group_by on that object so if there is no primary key attributed filled out it will reduce the records to 1 object. ex: rows = foo.find(:all,:select=>“boo.id, foo.name, foo.age, count(DISTINCT foo.id)”, :group=>“foo.name,foo.age having count( DISTINCT foo.id) > 1”,:joins=>“INNER JOIN bar.foo on bar.foo_id = foo.id”)
preload_assications(rows,:bar)
rows.first.bar.name #=> sql call already made in preload rows.last.bar.name #=> just made another sql call to get bar
fix: :select=>“foo.id, boo.id, foo.name, foo.age, count(DISTINCT foo.id)”
now preload_associations will include all the ids found instead of just the 1st one.