README.md in closure_tree-3.0.0 vs README.md in closure_tree-3.0.1
- old
+ new
@@ -1,18 +1,19 @@
# Closure Tree
Closure Tree is a mostly-API-compatible replacement for the
acts_as_tree and awesome_nested_set gems, but with much better
-mutation performance thanks to the Closure Tree storage algorithm.
+mutation performance thanks to the Closure Tree storage algorithm,
+as well as support for polymorphism within the hierarchy.
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.
## Setup
-Note that closure_tree is being developed for Rails 3.1.x
+Note that closure_tree supports Rails 3. Rails 2, not so much.
1. Add this to your Gemfile: ```gem 'closure_tree'```
2. Run ```bundle install```
@@ -20,39 +21,39 @@
4. Add a migration to add a ```parent_id``` column to the model you want to act_as_tree.
Note that if the column is null, the tag will be considered a root node.
- ```ruby
- class AddParentIdToTag < ActiveRecord::Migration
- def change
- add_column :tag, :parent_id, :integer
- end
+ ```ruby
+ class AddParentIdToTag < ActiveRecord::Migration
+ def change
+ add_column :tag, :parent_id, :integer
end
- ```
+ end
+ ```
5. Add a database migration to store the hierarchy for your model. By
convention the table name will be the model's table name, followed by
"_hierarchy". Note that by calling ```acts_as_tree```, a "virtual model" (in this case, ```TagsHierarchy```) will be added automatically, so you don't need to create it.
- ```ruby
- class CreateTagHierarchies < ActiveRecord::Migration
- def change
- create_table :tag_hierarchies, :id => false do |t|
- t.integer :ancestor_id, :null => false # ID of the parent/grandparent/great-grandparent/... tag
- t.integer :descendant_id, :null => false # ID of the target tag
- t.integer :generations, :null => false # Number of generations between the ancestor and the descendant. Parent/child = 1, for example.
- end
+ ```ruby
+ class CreateTagHierarchies < ActiveRecord::Migration
+ def change
+ create_table :tag_hierarchies, :id => false do |t|
+ t.integer :ancestor_id, :null => false # ID of the parent/grandparent/great-grandparent/... tag
+ t.integer :descendant_id, :null => false # ID of the target tag
+ t.integer :generations, :null => false # Number of generations between the ancestor and the descendant. Parent/child = 1, for example.
+ end
- # For "all progeny of..." selects:
- add_index :tag_hierarchies, [:ancestor_id, :descendant_id], :unique => true
+ # For "all progeny of..." selects:
+ add_index :tag_hierarchies, [:ancestor_id, :descendant_id], :unique => true
- # For "all ancestors of..." selects
- add_index :tag_hierarchies, [:descendant_id]
- end
+ # For "all ancestors of..." selects
+ add_index :tag_hierarchies, [:descendant_id]
end
- ```
+ end
+ ```
6. Run ```rake db:migrate```
7. If you're migrating away from another system where your model already has a
```parent_id``` column, run ```Tag.rebuild!``` and the
@@ -64,45 +65,45 @@
### Creation
Create a root node:
- ```ruby
- grandparent = Tag.create(:name => 'Grandparent')
- ```
+```ruby
+grandparent = Tag.create(:name => 'Grandparent')
+```
Child nodes are created by appending to the children collection:
- ```ruby
- child = parent.children.create(:name => 'Child')
- ```
+```ruby
+child = parent.children.create(:name => 'Child')
+```
You can also append to the children collection:
- ```ruby
- child = Tag.create(:name => 'Child')
- parent.children << child
- ```
+```ruby
+child = Tag.create(:name => 'Child')
+parent.children << child
+```
Or call the "add_child" method:
- ```ruby
- parent = Tag.create(:name => 'Parent')
- grandparent.add_child parent
- ```
+```ruby
+parent = Tag.create(:name => 'Parent')
+grandparent.add_child parent
+```
Then:
- ```ruby
- puts grandparent.self_and_descendants.collect{ |t| t.name }.join(" > ")
- "grandparent > parent > child"
+```ruby
+puts grandparent.self_and_descendants.collect{ |t| t.name }.join(" > ")
+"grandparent > parent > child"
- child.ancestry_path
- ["grandparent", "parent", "child"]
- ```
+child.ancestry_path
+["grandparent", "parent", "child"]
+```
-### <code>find_or_create_by_path</code>
+### find_or_create_by_path
We can do all the node creation and add_child calls from the prior section with one method call:
```ruby
child = Tag.find_or_create_by_path(["grandparent", "parent", "child"])
@@ -113,13 +114,13 @@
column is ```name```, which can be changed with the :name_column option
provided to ```acts_as_tree```.
Note that any other AR fields can be set with the second, optional ```attributes``` argument.
- ```ruby
- child = Tag.find_or_create_by_path(%w{home chuck Photos"}, {:tag_type => "File"})
- ```
+```ruby
+child = Tag.find_or_create_by_path(%w{home chuck Photos"}, {:tag_type => "File"})
+```
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).
### Available options
@@ -166,18 +167,18 @@
Polymorphic models are supported:
1. Create a db migration that adds a String ```type``` column to your model
2. Subclass the model class. You only need to add acts_as_tree to your base class.
- ```ruby
- class Tag < ActiveRecord::Base
- acts_as_tree
- end
- class WhenTag < Tag ; end
- class WhereTag < Tag ; end
- class WhatTag < Tag ; end
- ```
+```ruby
+class Tag < ActiveRecord::Base
+ acts_as_tree
+end
+class WhenTag < Tag ; end
+class WhereTag < Tag ; end
+class WhatTag < Tag ; end
+```
## Change log
### 2.0.0
@@ -189,9 +190,13 @@
### 3.0.0
* Support for polymorphic trees
* ```find_by_path``` and ```find_or_create_by_path``` signatures changed to support constructor attributes
* tested against Rails 3.1.3
+
+### 3.0.1
+
+* Support 3.2.0's fickle deprecation of InstanceMethods (Thanks, [jheiss](https://github.com/mceachen/closure_tree/pull/5))!
## Thanks to
* https://github.com/collectiveidea/awesome_nested_set
* https://github.com/patshaughnessy/class_factory