Skip to content

Commit 59238dc

Browse files
author
Tom Smyth
committed
Added documentation for has_closure_tree_root
1 parent d056bfe commit 59238dc

File tree

1 file changed

+45
-6
lines changed

1 file changed

+45
-6
lines changed

README.md

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ for a description of different tree storage algorithms.
5757

5858
Note that closure_tree only supports ActiveRecord 4.1 and later, and has test coverage for MySQL, PostgreSQL, and SQLite.
5959

60-
1. Add `gem 'closure_tree'` to your Gemfile
60+
1. Add `gem 'closure_tree'` to your Gemfile
6161

6262
2. Run `bundle install`
6363

@@ -74,7 +74,7 @@ Note that closure_tree only supports ActiveRecord 4.1 and later, and has test co
7474
```
7575

7676
Make sure you check out the [large number options](#available-options) that `has_closure_tree` accepts.
77-
77+
7878
**IMPORTANT: Make sure you add `has_closure_tree` _after_ `attr_accessible` and
7979
`self.table_name =` lines in your model.**
8080

@@ -114,9 +114,9 @@ NOTE: Run `rails g closure_tree:config` to create an initializer with extra
114114
115115
## Warning
116116
117-
As stated above, using multiple hierarchy gems (like `ancestry` or `nested set`) on the same model
117+
As stated above, using multiple hierarchy gems (like `ancestry` or `nested set`) on the same model
118118
will most likely result in pain, suffering, hair loss, tooth decay, heel-related ailments, and gingivitis.
119-
Assume things will break.
119+
Assume things will break.
120120
121121
## Usage
122122
@@ -168,7 +168,7 @@ child1.ancestry_path
168168
169169
You can `find` as well as `find_or_create` by "ancestry paths".
170170
171-
If you provide an array of strings to these methods, they reference the `name` column in your
171+
If you provide an array of strings to these methods, they reference the `name` column in your
172172
model, which can be overridden with the `:name_column` option provided to `has_closure_tree`.
173173
174174
```ruby
@@ -255,6 +255,45 @@ server may not be happy trying to do this.
255255
256256
HT: [ancestry](https://github.com/stefankroes/ancestry#arrangement) and [elhoyos](https://github.com/mceachen/closure_tree/issues/11)
257257
258+
### Eager loading
259+
260+
Since most of closure_tree's methods (e.g. `children`) return regular `ActiveRecord` scopes, you can use the `includes` method for eager loading, e.g.
261+
262+
```ruby
263+
comment.children.includes(:author)
264+
```
265+
266+
However, note that the above approach only eager loads the requested associations for the immediate children of `comment`. If you want to walk through the entire tree, you may still end up making many queries and loading duplicate copies of objects.
267+
268+
In some cases, a viable alternative is the following:
269+
270+
```ruby
271+
comment.self_and_descendants.includes(:author)
272+
```
273+
274+
This would load authors for `comment` and all its descendants in a constant number of queries. However, the return value is an array of `Comment`s, and the tree structure is thus lost, which makes it difficult to walk the tree using elegant recursive algorithms.
275+
276+
A third option is to use `has_closure_tree_root` on the model that is composed by the closure_tree model (e.g. a `Post` may be composed by a tree of `Comment`s). So in `post.rb`, you would do:
277+
278+
```ruby
279+
# app/models/post.rb
280+
has_closure_tree_root :root_comment
281+
```
282+
283+
This gives you a plain `has_one` association (`root_comment`) to the root `Comment` (i.e. that with null `parent_id`).
284+
285+
It also gives you a method called `root_comment_including_tree`, which you can invoke as follows:
286+
287+
```ruby
288+
a_post.root_comment_including_tree(:author)
289+
```
290+
291+
The result of this call will be the root `Comment` with all descendants _and_ associations loaded in a constant number of queries. Inverse associations are also setup on all nodes, so as you walk the tree, calling `children` or `parent` on any node will _not_ trigger any further queries and no duplicate copies of objects are loaded into memory.
292+
293+
The class and foreign key of `root_comment` are assumed to be `Comment` and `post_id`, respectively. These can be overridden in the usual way.
294+
295+
The same caveat stated above with `hash_tree` also applies here: this method will load the entire tree into memory. If the tree is very large, this may be a bad idea, in which case using the eager loading methods above may be preferred.
296+
258297
### Graph visualization
259298

260299
```to_dot_digraph``` is suitable for passing into [Graphviz](http://www.graphviz.org/).
@@ -472,7 +511,7 @@ Yup! [Ilya Bodrov](https://github.com/bodrovis) wrote [Nested Comments with Rail
472511

473512
### Can I update parentage with `update_attribute`?
474513

475-
**No.** `update_attribute` skips the validation hook that is required for maintaining the
514+
**No.** `update_attribute` skips the validation hook that is required for maintaining the
476515
hierarchy table.
477516

478517
### Does this gem support multiple parents?

0 commit comments

Comments
 (0)