closure_tree 1.0.0.beta5 → 1.0.0.beta6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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