Eleo wrote:
discussion = Discussion.find(:first, :include => [:posts])
Seems simple enough and it grabs an entire tree of posts. However:
discussion.posts.first.children
will run a MySQL query instead of (more smartly) simply accessing the
already eager-loaded posts.
To avoid a query you have to eager load all the levels you'll be accessing:
discussion = Discussion.find(:first, :include => {:posts => :children})
Eleo wrote:
That doesn't make any sense to me though. When I do Dicussion.find(:first, :include => [:posts]) I have effectively grabbed all the posts, including the children and those children and so on. All of the posts, including children, have the same discussion_id, after all.
Another problem with :include => {:posts => :children} is that it only grabs one level of children. I can make the include argument more complex but there's no way to know how deep a tree is.
I've found a better way to get children without queries is something like:
discussion.posts.collect {|post| if post.parent_id = num}.compact
Which will grab the children of a certain parent. This of course only works if I indeed have an entire tree of posts pre-loaded.
OK, I didn't realise discussion.posts contained every post in
the discussion, rather than just the top-level posts.
Perhaps you should use Better Nested Set:
http://opensource.symetrie.com/trac/better_nested_set/
This will allow you to fetch the posts in depth-first order,
so you can render whole discussion trees without searching,
sorting, or re-querying.
Eleo wrote:
I am using better nested set right now, but I don't see precisely how I'm supposed to render without searching/sorting/querying. As it is, foo.children or the like will still query the database. Can you elaborate on how this is supposed to work, please?
Fetch all posts using discussion.posts.find(:all, :order => 'lft'),
then write a recursive rendering function that loops through these,
watching for the parent_id to change, increasing the depth by one when
it changes to the id of the previous object, otherwise popping back up
the levels until the parent_ids match.