has_closure_tree_root - Better tree eager loading #232
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
So many times in working with trees I have a model, say Group, that has an associated tree, say of Users (say, with parent/child relationship defined by referral, as in the closure_tree specs). I keep a reference to the root of the tree, and would like to be able to load the root and all its descendants. I know that self_and_descendants can do this, but I want two things in addition:
.parent
and.children
methods. This is the way you're supposed to traverse a tree and this is how tree recursion typically and elegantly works.Unless I'm missing something, there is no way to do this currently. self_and_descendants gives you #2 but not #1.
This PR allows both. The basic idea is you declare:
This defines a plain
has_one
association to the root node (no preloading here), but also lets you do:which loads all Users, Contracts, and ContractTypes in 4 queries, no matter how many nodes are in the tree.
.parent
and.children
work as expected. Once the root is loaded, something likeroot.children[0].children[0].contracts[0].user.parent.parent.children[1].children[1].contracts[0].contract_type.name
triggers zero queries (not that you would ever write this line directly, but you get the idea).It also preloads the inverse belongs_to :group association on User, if that association is defined. So
root.children[0].group
also triggers zero queries.I'm curious for your thoughts on this. It's been very useful in my projects and curious if you think it would be a useful addition.
And thanks for the always awesome closure_tree!