closure_tree 1.0.0.beta5 → 1.0.0.beta6

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,137 @@
1
+ # Closure Tree
2
+
3
+ Closure Tree is a mostly-API-compatible replacement for the
4
+ acts_as_tree and awesome_nested_set gems, but with much better
5
+ mutation performance thanks to the Closure Tree storage algorithm.
6
+
7
+ See [Bill Karwin](http://karwin.blogspot.com/)'s excellent
8
+ [Models for hierarchical data presentation](http://www.slideshare.net/billkarwin/models-for-hierarchical-data)
9
+ for a description of different tree storage algorithms.
10
+
11
+ ## Setup
12
+
13
+ Note that closure_tree is being developed for Rails 3.1.0.rc1
14
+
15
+ 1. Add this to your Gemfile: ```gem 'closure_tree'```
16
+
17
+ 2. Run ```bundle install```
18
+
19
+ 3. Add ```acts_as_tree``` to your hierarchical model(s).
20
+
21
+ 4. Add a migration to add a ```parent_id``` column to the model you want to act_as_tree.
22
+
23
+ Note that if the column is null, the tag will be considered a root node.
24
+
25
+ ```ruby
26
+ class AddParentIdToTag < ActiveRecord::Migration
27
+ def change
28
+ add_column :tag, :parent_id, :integer
29
+ end
30
+ end
31
+ ```
32
+
33
+ 5. Add a database migration to store the hierarchy for your model. By
34
+ convention the table name will be the model's table name, followed by
35
+ "_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.
36
+
37
+ ```ruby
38
+ class CreateTagHierarchy < ActiveRecord::Migration
39
+ def change
40
+ create_table :tags_hierarchy, :id => false do |t|
41
+ t.integer :ancestor_id, :null => false # ID of the parent/grandparent/great-grandparent/... tag
42
+ t.integer :descendant_id, :null => false # ID of the target tag
43
+ t.integer :generations, :null => false # Number of generations between the ancestor and the descendant. Parent/child = 1, for example.
44
+ end
45
+
46
+ # For "all progeny of..." selects:
47
+ add_index :tags_hierarchy, [:ancestor_id, :descendant_id], :unique => true
48
+
49
+ # For "all ancestors of..." selects
50
+ add_index :tags_hierarchy, [:descendant_id]
51
+ end
52
+ end
53
+ ```
54
+
55
+ 6. Run ```rake db:migrate```
56
+
57
+ 7. If you're migrating away from another system where your model already has a
58
+ ```parent_id``` column, run ```Tag.rebuild!``` and the
59
+ ..._hierarchy table will be truncated and rebuilt.
60
+
61
+ If you're starting from scratch you don't need to call ```rebuild!```.
62
+
63
+ ## Usage
64
+
65
+ ### Creation
66
+
67
+ Create a root node:
68
+
69
+ ```ruby
70
+ grandparent = Tag.create!(:name => 'Grandparent')
71
+ ```
72
+
73
+ There are two equivalent ways to add children. Either use the ```add_child``` method:
74
+
75
+ ```ruby
76
+ parent = Tag.create!(:name => 'Parent')
77
+ grandparent.add_child parent
78
+ ```
79
+
80
+ Or append to the ```children``` collection:
81
+
82
+ ```ruby
83
+ child = Tag.create!(:name => 'Child')
84
+ parent.children << child
85
+ ```
86
+
87
+ Then:
88
+
89
+ ```ruby
90
+ puts grandparent.self_and_descendants.collect{ |t| t.name }.join(" > ")
91
+ "grandparent > parent > child"
92
+
93
+ child.ancestry_path
94
+ ["grandparent", "parent", "child"]
95
+ ```
96
+
97
+ ### <code>find_or_create_by_path</code>
98
+
99
+ We can do all the node creation and add_child calls from the prior section with one method call:
100
+
101
+ ```ruby
102
+ child = Tag.find_or_create_by_path "grandparent", "parent", "child"
103
+ ```
104
+
105
+ 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```.
106
+
107
+ Note that the other columns will be null if nodes are created, other than auto-generated columns like ID and created_at timestamp. Only the specified column will receive the path element value.
108
+
109
+ ## Accessing Data
110
+
111
+ ### Class methods
112
+
113
+ * ``` Tag.root``` returns an arbitrary root node
114
+ * ``` Tag.roots``` returns all root nodes
115
+ * ``` Tag.leaves``` returns all leaf nodes
116
+
117
+ ### Instance methods
118
+
119
+ * ``` tag.root``` returns the root for this node
120
+ * ``` tag.root?``` returns true if this is a root node
121
+ * ``` tag.child?``` returns true if this is a child node. It has a parent.
122
+ * ``` tag.leaf?``` returns true if this is a leaf node. It has no children.
123
+ * ``` tag.leaves``` returns an array of all the nodes in self_and_descendants that are leaves.
124
+ * ``` tag.level``` returns the level, or "generation", for this node in the tree. A root node = 0
125
+ * ``` tag.parent``` returns the node's immediate parent
126
+ * ``` tag.children``` returns an array of immediate children (just those in the next level).
127
+ * ``` tag.ancestors``` returns an array of all parents, parents' parents, etc, excluding self.
128
+ * ``` tag.self_and_ancestors``` returns an array of all parents, parents' parents, etc, including self.
129
+ * ``` tag.siblings``` returns an array of brothers and sisters (all at that level), excluding self.
130
+ * ``` tag.self_and_siblings``` returns an array of brothers and sisters (all at that level), including self.
131
+ * ``` tag.descendants``` returns an array of all children, childrens' children, etc., excluding self.
132
+ * ``` tag.self_and_descendants``` returns an array of all children, childrens' children, etc., including self.
133
+
134
+ ## Thanks to
135
+
136
+ * https://github.com/collectiveidea/awesome_nested_set
137
+ * https://github.com/patshaughnessy/class_factory
data/Rakefile CHANGED
@@ -6,18 +6,12 @@ end
6
6
 
7
7
  Bundler::GemHelper.install_tasks
8
8
 
9
+ require 'yard'
9
10
 
10
- require 'rdoc/task'
11
-
12
- RDoc::Task.new do |rdoc|
13
- rdoc.rdoc_dir = 'rdoc'
14
- rdoc.title = 'ClosureTree'
15
- rdoc.options << '--line-numbers' << '--inline-source'
16
- rdoc.rdoc_files.include('README.rdoc')
17
- rdoc.rdoc_files.include('lib/**/*.rb')
11
+ YARD::Rake::YardocTask.new do |t|
12
+ t.files = ['lib/**/*.rb', 'README.md']
18
13
  end
19
14
 
20
-
21
15
  require 'rake/testtask'
22
16
 
23
17
  Rake::TestTask.new(:test) do |t|
@@ -1,3 +1,3 @@
1
1
  module ClosureTree
2
- VERSION = "1.0.0.beta5" unless defined?(::ClosureTree::VERSION)
2
+ VERSION = "1.0.0.beta6" unless defined?(::ClosureTree::VERSION)
3
3
  end
metadata CHANGED
@@ -1,19 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: closure_tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.beta5
4
+ version: 1.0.0.beta6
5
5
  prerelease: 6
6
6
  platform: ruby
7
- authors: []
7
+ authors:
8
+ - matthew-github@mceachen.org
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2011-05-29 00:00:00.000000000 -07:00
12
+ date: 2011-07-02 00:00:00.000000000 -07:00
12
13
  default_executable:
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: activerecord
16
- requirement: &2160266260 !ruby/object:Gem::Requirement
17
+ requirement: &2162178320 !ruby/object:Gem::Requirement
17
18
  none: false
18
19
  requirements:
19
20
  - - ! '>='
@@ -21,7 +22,7 @@ dependencies:
21
22
  version: 3.0.0
22
23
  type: :runtime
23
24
  prerelease: false
24
- version_requirements: *2160266260
25
+ version_requirements: *2162178320
25
26
  description: ! " A mostly-API-compatible replacement for the acts_as_tree and awesome_nested_set
26
27
  gems,\n but with much better mutation performance thanks to the Closure Tree storage
27
28
  algorithm\n"
@@ -36,7 +37,7 @@ files:
36
37
  - lib/tasks/closure_tree_tasks.rake
37
38
  - MIT-LICENSE
38
39
  - Rakefile
39
- - README.rdoc
40
+ - README.md
40
41
  - test/dummy/Rakefile
41
42
  - test/dummy/app/models/.gitkeep
42
43
  - test/dummy/app/models/tag.rb
@@ -71,7 +72,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
71
72
  version: '0'
72
73
  segments:
73
74
  - 0
74
- hash: 1822137668731567771
75
+ hash: 1847009308530126687
75
76
  required_rubygems_version: !ruby/object:Gem::Requirement
76
77
  none: false
77
78
  requirements:
data/README.rdoc DELETED
@@ -1,122 +0,0 @@
1
- = Closure Tree
2
-
3
- Closure Tree is a mostly-API-compatible replacement for the
4
- acts_as_tree and awesome_nested_set gems, but with much better
5
- mutation performance thanks to the Closure Tree storage algorithm.
6
-
7
- See {Bill Karwin}[http://karwin.blogspot.com/]'s excellent
8
- {Models for hierarchical data presentation}[http://www.slideshare.net/billkarwin/models-for-hierarchical-data]
9
- for a description of different tree storage algorithms.
10
-
11
- == Setup
12
-
13
- Note that closure_tree is being developed for Rails 3.1.0.rc1
14
-
15
- 1. Add this to your Gemfile: <code>gem 'closure_tree'</code>
16
-
17
- 2. Run <code>bundle install</code>
18
-
19
- 3. Add <code>acts_as_tree</code> to your hierarchical model(s).
20
-
21
- 4. Add a migration to add a <code>parent_id</code> column to the model you want to act_as_tree.
22
-
23
- Note that if the column is null, the tag will be considered a root node.
24
-
25
- class AddParentIdToTag < ActiveRecord::Migration
26
- def change
27
- add_column :tag, :parent_id, :integer
28
- end
29
- end
30
-
31
- 5. Add a database migration to store the hierarchy for your model. By
32
- convention the table name will be the model's table name, followed by
33
- "_hierarchy". Note that by calling <code>acts_as_tree</code>, a "virtual model" (in this case, <code>TagsHierarchy</code>) will be added automatically, so you don't need to create it.
34
-
35
- class CreateTagHierarchy < ActiveRecord::Migration
36
- def change
37
- create_table :tags_hierarchy, :id => false do |t|
38
- t.integer :ancestor_id, :null => false # ID of the parent/grandparent/great-grandparent/... tag
39
- t.integer :descendant_id, :null => false # ID of the target tag
40
- t.integer :generations, :null => false # Number of generations between the ancestor and the descendant. Parent/child = 1, for example.
41
- end
42
-
43
- # For "all progeny of..." selects:
44
- add_index :tags_hierarchy, [:ancestor_id, :descendant_id], :unique => true
45
-
46
- # For "all ancestors of..." selects
47
- add_index :tags_hierarchy, [:descendant_id]
48
- end
49
- end
50
-
51
- 6. Run <code>rake db:migrate</code>
52
-
53
- 7. If you're migrating away from another system where your model already has a
54
- <code>parent_id</code> column, run <code>Tag.rebuild!</code> and the
55
- ..._hierarchy table will be truncated and rebuilt.
56
-
57
- If you're starting from scratch you don't need to call <code>rebuild!</code>.
58
-
59
- == Usage
60
-
61
- === Creation
62
-
63
- Create a root node:
64
-
65
- grandparent = Tag.create!(:name => 'Grandparent')
66
-
67
- There are two equivalent ways to add children. Either use the <code>add_child</code> method:
68
-
69
- parent = Tag.create!(:name => 'Parent')
70
- grandparent.add_child parent
71
-
72
- Or append to the <code>children</code> collection:
73
-
74
- child = Tag.create!(:name => 'Child')
75
- parent.children << child
76
-
77
- Then:
78
-
79
- puts grandparent.self_and_descendants.collect{ |t| t.name }.join(" > ")
80
- "grandparent > parent > child"
81
-
82
- child.ancestry_path
83
- ["grandparent", "parent", "child"]
84
-
85
- === <code>find_or_create_by_path</code>
86
-
87
- We can do all the node creation and add_child calls from the prior section with one method call:
88
- child = Tag.find_or_create_by_path "grandparent", "parent", "child"
89
-
90
- You can <code>find</code> as well as <code>find_or_create</code> by "ancestry paths". Ancestry paths may be built using any column in your model. The default column is <code>name</code>, which can be changed with the :name_column option provided to <code>acts_as_tree</code>.
91
-
92
- Note that the other columns will be null if nodes are created, other than auto-generated columns like ID and created_at timestamp. Only the specified column will receive the path element value.
93
-
94
- == Accessing Data
95
-
96
- === Class methods
97
-
98
- [Tag.root] returns an arbitrary root node
99
- [Tag.roots] returns all root nodes
100
- [Tag.leaves] returns all leaf nodes
101
-
102
- === Instance methods
103
-
104
- [tag.root] returns the root for this node
105
- [tag.root?] returns true if this is a root node
106
- [tag.child?] returns true if this is a child node. It has a parent.
107
- [tag.leaf?] returns true if this is a leaf node. It has no children.
108
- [tag.leaves] returns an array of all the nodes in self_and_descendants that are leaves.
109
- [tag.level] returns the level, or "generation", for this node in the tree. A root node = 0
110
- [tag.parent] returns the node's immediate parent
111
- [tag.children] returns an array of immediate children (just those in the next level).
112
- [tag.ancestors] returns an array of all parents, parents' parents, etc, excluding self.
113
- [tag.self_and_ancestors] returns an array of all parents, parents' parents, etc, including self.
114
- [tag.siblings] returns an array of brothers and sisters (all at that level), excluding self.
115
- [tag.self_and_siblings] returns an array of brothers and sisters (all at that level), including self.
116
- [tag.descendants] returns an array of all children, childrens' children, etc., excluding self.
117
- [tag.self_and_descendants] returns an array of all children, childrens' children, etc., including self.
118
-
119
- == Thanks to
120
-
121
- * https://github.com/collectiveidea/awesome_nested_set
122
- * https://github.com/patshaughnessy/class_factory