closure_tree 3.4.3 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +12 -4
- data/lib/closure_tree/acts_as_tree.rb +33 -1
- data/lib/closure_tree/version.rb +1 -1
- data/spec/label_spec.rb +42 -0
- metadata +3 -3
data/README.md
CHANGED
@@ -203,6 +203,9 @@ When you include ```acts_as_tree``` in your model, you can provide a hash to ove
|
|
203
203
|
* ```Tag.roots``` returns all root nodes
|
204
204
|
* ```Tag.leaves``` returns all leaf nodes
|
205
205
|
* ```Tag.hash_tree``` returns an [ordered, nested hash](#nested-hashes) that can be depth-limited.
|
206
|
+
* ```Tag.find_by_path(path)``` returns the node whose name path is ```path```. See (#find_or_create_by_path).
|
207
|
+
* ```Tag.find_or_create_by_path(path)``` returns the node whose name path is ```path```, and will create the node if it doesn't exist already.See (#find_or_create_by_path).
|
208
|
+
* ```Tag.find_all_by_generation(generation_level)``` returns the descendant nodes who are ```generation_level``` away from a root. ```Tag.find_all_by_generation(0)``` is equivalent to ```Tag.roots```.
|
206
209
|
|
207
210
|
### Instance methods
|
208
211
|
|
@@ -224,6 +227,12 @@ When you include ```acts_as_tree``` in your model, you can provide a hash to ove
|
|
224
227
|
* ```tag.descendant_ids``` returns an array of the IDs of the descendants.
|
225
228
|
* ```tag.self_and_descendants``` returns a scope of all children, childrens' children, etc., including self, ordered by depth.
|
226
229
|
* ```tag.hash_tree``` returns an [ordered, nested hash](#nested-hashes) that can be depth-limited.
|
230
|
+
* ```tag.find_by_path(path)``` returns the node whose name path *from ```tag```* is ```path```. See (#find_or_create_by_path).
|
231
|
+
* ```tag.find_or_create_by_path(path)``` returns the node whose name path *from ```tag```* is ```path```, and will create the node if it doesn't exist already.See (#find_or_create_by_path).
|
232
|
+
* ```tag.find_all_by_generation(generation_level)``` returns the descendant nodes who are ```generation_level``` away from ```tag```.
|
233
|
+
* ```tag.find_all_by_generation(0).to_a``` == ```[tag]```
|
234
|
+
* ```tag.find_all_by_generation(1)``` == ```tag.children```
|
235
|
+
* ```tag.find_all_by_generation(2)``` will return the tag's grandchildren, and so on.
|
227
236
|
* ```tag.destroy``` will destroy a node and do <em>something</em> to its children, which is determined by the ```:dependent``` option passed to ```acts_as_tree```.
|
228
237
|
|
229
238
|
## <a id="sti"></a>Polymorphic hierarchies with STI
|
@@ -320,13 +329,12 @@ Closure tree is [tested under every combination](http://travis-ci.org/#!/mceache
|
|
320
329
|
* The latest Rails 3.0, 3.1, and 3.2 branches, and
|
321
330
|
* MySQL, PostgreSQL, and SQLite.
|
322
331
|
|
323
|
-
|
324
332
|
## Change log
|
325
333
|
|
326
|
-
### 3.
|
334
|
+
### 3.5.0
|
327
335
|
|
328
|
-
*
|
329
|
-
|
336
|
+
* Added ```find_all_by_generation```
|
337
|
+
for [feature request 17](https://github.com/mceachen/closure_tree/issues/17)).
|
330
338
|
|
331
339
|
### 3.4.2
|
332
340
|
|
@@ -87,6 +87,25 @@ module ClosureTree
|
|
87
87
|
roots.inject(ActiveSupport::OrderedHash.new) { |h, ea| h.merge(ea.hash_tree(options)) }
|
88
88
|
end
|
89
89
|
|
90
|
+
def find_all_by_generation(generation_level)
|
91
|
+
s = joins(<<-SQL)
|
92
|
+
INNER JOIN (
|
93
|
+
SELECT #{primary_key} as root_id
|
94
|
+
FROM #{quoted_table_name}
|
95
|
+
WHERE #{quoted_parent_column_name} IS NULL
|
96
|
+
) AS roots
|
97
|
+
INNER JOIN (
|
98
|
+
SELECT ancestor_id, descendant_id
|
99
|
+
FROM #{quoted_hierarchy_table_name}
|
100
|
+
GROUP BY 1, 2
|
101
|
+
HAVING MAX(#{quoted_hierarchy_table_name}.generations) = #{generation_level.to_i}
|
102
|
+
) AS descendants
|
103
|
+
ON #{quoted_table_name}.#{primary_key} = descendants.descendant_id
|
104
|
+
AND roots.root_id = ancestor_id
|
105
|
+
SQL
|
106
|
+
order_option ? s.order(order_option) : s
|
107
|
+
end
|
108
|
+
|
90
109
|
def self.leaves
|
91
110
|
s = joins(<<-SQL)
|
92
111
|
INNER JOIN (
|
@@ -94,7 +113,7 @@ module ClosureTree
|
|
94
113
|
FROM #{quoted_hierarchy_table_name}
|
95
114
|
GROUP BY 1
|
96
115
|
HAVING MAX(#{quoted_hierarchy_table_name}.generations) = 0
|
97
|
-
) AS leaves ON
|
116
|
+
) AS leaves ON #{quoted_table_name}.#{primary_key} = leaves.ancestor_id
|
98
117
|
SQL
|
99
118
|
order_option ? s.order(order_option) : s
|
100
119
|
end
|
@@ -205,6 +224,19 @@ module ClosureTree
|
|
205
224
|
node
|
206
225
|
end
|
207
226
|
|
227
|
+
def find_all_by_generation(generation_level)
|
228
|
+
s = self.class.joins(<<-SQL)
|
229
|
+
INNER JOIN (
|
230
|
+
SELECT descendant_id
|
231
|
+
FROM #{quoted_hierarchy_table_name}
|
232
|
+
WHERE ancestor_id = #{self.id}
|
233
|
+
GROUP BY 1
|
234
|
+
HAVING MAX(#{quoted_hierarchy_table_name}.generations) = #{generation_level.to_i}
|
235
|
+
) AS descendants ON #{quoted_table_name}.#{self.class.primary_key} = descendants.descendant_id
|
236
|
+
SQL
|
237
|
+
order_option ? s.order(order_option) : s
|
238
|
+
end
|
239
|
+
|
208
240
|
def hash_tree(options = {})
|
209
241
|
tree = ActiveSupport::OrderedHash.new
|
210
242
|
tree[self] = ActiveSupport::OrderedHash.new
|
data/lib/closure_tree/version.rb
CHANGED
data/spec/label_spec.rb
CHANGED
@@ -65,6 +65,48 @@ describe Label do
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
+
context "find_all_by_generation" do
|
69
|
+
before :all do
|
70
|
+
nuke_db
|
71
|
+
@d1 = Label.find_or_create_by_path %w(a b c1 d1)
|
72
|
+
@d2 = Label.find_or_create_by_path %w(a b c2 d2)
|
73
|
+
@c1 = @d1.parent
|
74
|
+
@c2 = @d2.parent
|
75
|
+
@b = @c1.parent
|
76
|
+
@a = @b.parent
|
77
|
+
end
|
78
|
+
|
79
|
+
it "finds roots from the class method" do
|
80
|
+
Label.find_all_by_generation(1).to_a.should == [@b]
|
81
|
+
end
|
82
|
+
|
83
|
+
it "finds roots from themselves" do
|
84
|
+
@a.find_all_by_generation(0).to_a.should == [@a]
|
85
|
+
end
|
86
|
+
|
87
|
+
it "finds itself for non-roots" do
|
88
|
+
@b.find_all_by_generation(0).to_a.should == [@b]
|
89
|
+
end
|
90
|
+
|
91
|
+
it "finds children for roots" do
|
92
|
+
Label.find_all_by_generation(1).to_a.should == [@b]
|
93
|
+
end
|
94
|
+
|
95
|
+
it "finds children" do
|
96
|
+
@a.find_all_by_generation(1).to_a.should == [@b]
|
97
|
+
@b.find_all_by_generation(1).to_a.should == [@c1, @c2]
|
98
|
+
end
|
99
|
+
|
100
|
+
it "finds grandchildren for roots" do
|
101
|
+
Label.find_all_by_generation(2).to_a.should == [@c1, @c2]
|
102
|
+
end
|
103
|
+
|
104
|
+
it "finds grandchildren" do
|
105
|
+
@a.find_all_by_generation(2).to_a.should == [@c1, @c2]
|
106
|
+
@b.find_all_by_generation(2).to_a.should == [@d1, @d2]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
68
110
|
context "Deterministic siblings sort with custom integer column" do
|
69
111
|
nuke_db
|
70
112
|
fixtures :labels
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: closure_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -192,7 +192,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
192
192
|
version: '0'
|
193
193
|
segments:
|
194
194
|
- 0
|
195
|
-
hash:
|
195
|
+
hash: 1009921537345124595
|
196
196
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
197
|
none: false
|
198
198
|
requirements:
|
@@ -201,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
201
201
|
version: '0'
|
202
202
|
segments:
|
203
203
|
- 0
|
204
|
-
hash:
|
204
|
+
hash: 1009921537345124595
|
205
205
|
requirements: []
|
206
206
|
rubyforge_project:
|
207
207
|
rubygems_version: 1.8.23
|