eager loading parents and children (acts_as_tree)

Carl Johnson wrote:

I am struggling with how to do eager loading of an acts_as_tree model.

If the model Stuff acts_as_tree I know I can do this to get children as well:

Stuff.find(:all, :include => :children)

But what if the model I am including is the one that acts_as_tree?

For example, say Picture belongs_to Category. Category acts_as_tree and I want to get all pictures that are members of a category that belong to a particular user and ALSO all pictures in children of those categories (one level of children is fine). I believe this is the correct syntax:

Pictures.find(:all, :include => {:category => :children}, :conditions => ['categories.user_id = ?', @user.id])

This does not seem to work. I'm only getting pictures that belong to root categories. Can anyone tell me what I'm doing wrong? I have a feeling that I'm thinking about this the wrong way somehow.

I think you need something like:

Pictures.find :all, :include => {:category => :parent}, :conditions => <<-END    categories.user_id = #{@user.id} or parent_categories.user_id = #{@user.id} END

Carl Johnson wrote:

> I think you need something like:

Pictures.find :all, :include => {:category => :parent}, :conditions => <<-END    categories.user_id = #{@user.id} or parent_categories.user_id = #{@user.id} END

You're right! That worked perfectly (though the condition is parents_categories). Thank you!!

Now I need to try and understand the difference in the joins of :children versus :parent. It seems a bit counter-intuitive to include :parent when you want to make sure children are returned. I guess this just means I am joining the parent_id field of children to their parents, basically...?

The first level of category is that of the pictures being returned, so you want to specify both the owners of these categories and the owners of the categories for which these categories are child categories -- that is owners of parent categories of these categories.

Using include gives you a neat query, but it's inefficient to attach two layers of category models to each picture if they're not being referenced in your code.

You can instead put the required joins explicitly in a :joins parameter, but this makes the query look more complicated.

It'd be nice if one could write :joins => {:category => :parent} and have Rails add the same joins and aliases as an :include, but not do either field aliasing or selection and attachment of the joined child models.