13
votes

In RoR, it is pretty common mistake for new people to load a class and assiocations like this# the solution to eager load

# The bellow generates an insane amount of queries
# post has many comments
# If you have 10 posts with 5 comments each
# this will run 11 queries 
posts = Post.find(:all)
posts.each do |post|
  post.comments
end

The solution is pretty simple to eager load

# should be 2 queries
# no matter how many posts you have
posts = Post.find(:all, :include => :comments) # runs a query to get all the comments for all the posts
posts.each do |post|
  post.comments # runs a query to get the comments for that post
end

But what if you don't have access to the class methods, and only have access to a collection of instance methods.

Then you are stuck with the query intensive lazy loading.

Is there a way to minimize queries to get all the comments for the collection of posts, from the collection of instances?

Addition for Answer (also added to the code above)


So to eager load from what I can see in the rdoc for rails is a class method on any extension of ActiveRecord::Associations, the problem is say you you don't have the ability to use a class method, so you need to use some sort of instance method

a code example of what I think it would look like would be is something like

post = Posts.find(:all)
posts.get_all(:comments) # runs the query to build comments into each post without the class method.
3

3 Answers

26
votes

In Rails 3.0 and earlier you can do:

Post.send :preload_associations, posts, :comments

You can pass arrays or hashes of association names like you can to include:

Post.send :preload_associations, posts, :comments => :users

In Rails 3.1 this has been moved and you use the Preloader like this:

ActiveRecord::Associations::Preloader.new(posts, :comments).run()

And since Rails 4 its invocation has changed to:

ActiveRecord::Associations::Preloader.new.preload(posts, :comments)
0
votes

I think I get what you're asking.

However, I don't think you have to worry about what methods you have access to. The foreign key relationship (and the ActiveRecord associations, such as has_many, belongs_to, etc.) will take care of figuring out how to load the associated records.

If you can provide a specific example of what you think should happen, and actual code that isn't working, it would be easier to see what you're getting at.

0
votes

How are you obtaining your collection of model instances, and what version of Rails are you using?

Are you saying that you have absolutely no access to either controllers or models themselves?

giving you the best answer depends on knowing those things.