README.md in closure_tree-4.6.3 vs README.md in closure_tree-5.0.0
- old
+ new
@@ -8,11 +8,11 @@
[![Build Status](https://secure.travis-ci.org/mceachen/closure_tree.png?branch=master)](http://travis-ci.org/mceachen/closure_tree)
[![Gem Version](https://badge.fury.io/rb/closure_tree.png)](http://rubygems.org/gems/closure_tree)
[![Code Climate](https://codeclimate.com/github/mceachen/closure_tree.png)](https://codeclimate.com/github/mceachen/closure_tree)
[![Dependency Status](https://gemnasium.com/mceachen/closure_tree.png)](https://gemnasium.com/mceachen/closure_tree)
-Substantially more efficient than
+Dramatically more performant than
[ancestry](https://github.com/stefankroes/ancestry) and
[acts_as_tree](https://github.com/amerine/acts_as_tree), and even more
awesome than [awesome_nested_set](https://github.com/collectiveidea/awesome_nested_set/),
closure_tree has some great features:
@@ -23,20 +23,20 @@
* Fetch all [descendants as a nested hash](#nested-hashes) in 1 SELECT.
* [Find a node by ancestry path](#find_or_create_by_path) in 1 SELECT.
* __Best-in-class mutation performance__:
* 2 SQL INSERTs on node creation
* 3 SQL INSERT/UPDATEs on node reparenting
+* __Support for [concurrency](#concurrency)__ (using [with_advisory_lock](https://github.com/mceachen/with_advisory_lock))
* __Support for Rails 3.2, 4.0, and 4.1__
-* __Support for Ruby 1.9 and 2.1 (jRuby and Rubinius are still in development)__
+* __Support for Ruby 1.9, 2.1, and jRuby 1.6.13
* Support for reparenting children (and all their descendants)
-* Support for [concurrency](#concurrency) (using [with_advisory_lock](https://github.com/mceachen/with_advisory_lock))
-* Support for polymorphism [STI](#sti) within the hierarchy
-* ```find_or_create_by_path``` for [building out hierarchies quickly and conveniently](#find_or_create_by_path)
-* Support for [deterministic ordering](#deterministic-ordering) of children
+* Support for [single-table inheritance (STI)](#sti) within the hierarchy
+* ```find_or_create_by_path``` for [building out heterogeneous hierarchies quickly and conveniently](#find_or_create_by_path)
+* Support for [deterministic ordering](#deterministic-ordering)
* Support for [preordered](http://en.wikipedia.org/wiki/Tree_traversal#Pre-order) traversal of descendants
* Support for rendering trees in [DOT format](http://en.wikipedia.org/wiki/DOT_(graph_description_language)), using [Graphviz](http://www.graphviz.org/)
-* Excellent [test coverage](#testing) in a variety of environments
+* Excellent [test coverage](#testing) in a comprehensive variety of environments
See [Bill Karwin](http://karwin.blogspot.com/)'s excellent
[Models for hierarchical data presentation](http://www.slideshare.net/billkarwin/models-for-hierarchical-data)
for a description of different tree storage algorithms.
@@ -151,34 +151,44 @@
=> ["Grandparent", "Parent", "First Child"]
```
### find_or_create_by_path
-We can do all the node creation and add_child calls with one method call:
+You can ```find``` as well as ```find_or_create``` by "ancestry paths".
+If you provide an array of strings to these methods, they reference the `name` column in your
+model, which can be overridden with the `:name_column` option provided to ```acts_as_tree```.
+
```ruby
child = Tag.find_or_create_by_path(["grandparent", "parent", "child"])
```
-You can ```find``` as well as ```find_or_create``` by "ancestry paths".
-Ancestry paths may be built using any column in your model. The default
-column is ```name```, which can be changed with the :name_column option
-provided to ```acts_as_tree```.
+As of v5.0.0, `find_or_create_by_path` can also take an array of attribute hashes:
-Note that any other AR fields can be set with the second, optional ```attributes``` argument,
-and as of version 4.2.0, these attributes are added to the where clause as selection criteria.
+```ruby
+child = Tag.find_or_create_by_path([
+ {name: "Grandparent", title: "Sr."},
+ {name: "Parent", title: "Mrs."},
+ {name: "Child", title: "Jr."}
+])
+```
+If you're using STI, The attribute hashes can contain the `sti_name` and things work as expected:
+
```ruby
-child = Tag.find_or_create_by_path(%w{home chuck Photos"}, {:tag_type => "File"})
+child = Label.find_or_create_by_path([
+ {type: 'DateLabel', name: '2014'},
+ {type: 'DateLabel', name: 'August'},
+ {type: 'DateLabel', name: '5'},
+ {type: 'EventLabel', name: 'Visit the Getty Center'}
+])
```
-This will pass the attribute hash of ```{:name => "home", :tag_type => "File"}``` to
-```Tag.find_or_create_by_name``` if the root directory doesn't exist (and
-```{:name => "chuck", :tag_type => "File"}``` if the second-level tag doesn't exist, and so on).
### Moving nodes around the tree
-Nodes can be moved around to other parents, and closure_tree moves the node's descendancy to the new parent for you:
+Nodes can be moved around to other parents, and closure_tree moves the node's descendancy to the
+new parent for you:
```ruby
d = Tag.find_or_create_by_path %w(a b c d)
h = Tag.find_or_create_by_path %w(e f g h)
e = h.root
@@ -250,10 +260,11 @@
* ```:nullify``` will simply set the parent column to null. Each child node will be considered a "root" node. This is the default.
* ```:delete_all``` will delete all descendant nodes (which circumvents the destroy hooks)
* ```:destroy``` will destroy all descendant nodes (which runs the destroy hooks on each child node)
* ```:name_column``` used by #```find_or_create_by_path```, #```find_by_path```, and ```ancestry_path``` instance methods. This is primarily useful if the model only has one required field (like a "tag").
* ```:order``` used to set up [deterministic ordering](#deterministic-ordering)
+* ```:touch``` delegates to the `belongs_to` annotation for the parent, so `touch`ing cascades to all children (the performance of this for deep trees isn't currently optimal).
## Accessing Data
### Class methods
@@ -526,10 +537,9 @@
# Expect syntax
it { is_expected.to be_a_closure_tree.ordered(:priority_order) }
end
```
-
## Testing
Closure tree is [tested under every valid combination](http://travis-ci.org/#!/mceachen/closure_tree) of