closure_tree 3.4.3 → 3.5.0
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 +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
|