Eager loading parents and children (acts_as_tree)


#1

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.

Thanks very much!


#2

Carl J. wrote:

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


We develop, watch us RoR, in numbers too big to ignore.


#3

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…?


#4

Carl J. wrote:

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.


We develop, watch us RoR, in numbers too big to ignore.