mongoid-ancestry 0.1.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/Gemfile +3 -0
- data/Gemfile.lock +75 -0
- data/Guardfile +10 -0
- data/MIT-LICENSE +20 -0
- data/README.md +225 -0
- data/Rakefile +42 -0
- data/VERSION +1 -0
- data/init.rb +1 -0
- data/install.rb +1 -0
- data/lib/mongoid/ancestry/class_methods.rb +233 -0
- data/lib/mongoid/ancestry/exceptions.rb +6 -0
- data/lib/mongoid/ancestry/instance_methods.rb +246 -0
- data/lib/mongoid/ancestry.rb +14 -0
- data/log/.gitkeep +0 -0
- data/mongoid-ancestry.gemspec +125 -0
- data/spec/mongoid/ancestry/class_methods_spec.rb +305 -0
- data/spec/mongoid/ancestry/instance_methods_spec.rb +266 -0
- data/spec/mongoid/ancestry_spec.rb +117 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/support/models.rb +44 -0
- metadata +310 -0
@@ -0,0 +1,266 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MongoidAncestry do
|
4
|
+
|
5
|
+
subject { MongoidAncestry }
|
6
|
+
|
7
|
+
it "should be saved with unique id for new records" do
|
8
|
+
subject.with_model do |model|
|
9
|
+
new_record = model.create!
|
10
|
+
new_record.uid.should eql(1)
|
11
|
+
expect { new_record.save }.to_not change(new_record, :uid)
|
12
|
+
expect { new_record.save! }.to_not change(new_record, :uid)
|
13
|
+
model.create.uid.should eql(2)
|
14
|
+
model.create!.uid.should eql(3)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should raise error on non unique id" do
|
19
|
+
subject.with_model do |model|
|
20
|
+
model.create_indexes
|
21
|
+
expect do
|
22
|
+
first_record = model.new
|
23
|
+
first_record.stub!(:set_uid => true)
|
24
|
+
first_record.save
|
25
|
+
second = model.new
|
26
|
+
second.should_receive(:set_uid).exactly(3).times.and_return(true)
|
27
|
+
second.save
|
28
|
+
end.to raise_error(Mongo::OperationFailure, /duplicate key error/)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should have tree navigation" do
|
33
|
+
subject.with_model :depth => 3, :width => 3 do |model, roots|
|
34
|
+
roots.each do |lvl0_node, lvl0_children|
|
35
|
+
# Ancestors assertions
|
36
|
+
lvl0_node.ancestor_ids.should eql([])
|
37
|
+
lvl0_node.ancestors.to_a.should eql([])
|
38
|
+
lvl0_node.path_ids.should eql([lvl0_node.uid])
|
39
|
+
lvl0_node.path.to_a.should eql([lvl0_node])
|
40
|
+
lvl0_node.depth.should eql(0)
|
41
|
+
# Parent assertions
|
42
|
+
lvl0_node.parent_id.should be_nil
|
43
|
+
lvl0_node.parent.should be_nil
|
44
|
+
# Root assertions
|
45
|
+
lvl0_node.root_id.should eql(lvl0_node.uid)
|
46
|
+
lvl0_node.root.should eql(lvl0_node)
|
47
|
+
lvl0_node.is_root?.should be_true
|
48
|
+
# Children assertions
|
49
|
+
lvl0_node.child_ids.should eql(lvl0_children.map(&:first).map(&:uid))
|
50
|
+
lvl0_node.children.to_a.should eql(lvl0_children.map(&:first))
|
51
|
+
lvl0_node.has_children?.should be_true
|
52
|
+
lvl0_node.is_childless?.should be_false
|
53
|
+
# Siblings assertions
|
54
|
+
lvl0_node.sibling_ids.should eql(roots.map(&:first).map(&:uid))
|
55
|
+
lvl0_node.siblings.to_a.should eql(roots.map(&:first))
|
56
|
+
lvl0_node.has_siblings?.should be_true
|
57
|
+
lvl0_node.is_only_child?.should be_false
|
58
|
+
# Descendants assertions
|
59
|
+
descendants = model.all.find_all do |node|
|
60
|
+
node.ancestor_ids.include?(lvl0_node.uid)
|
61
|
+
end
|
62
|
+
lvl0_node.descendant_ids.should eql(descendants.map(&:uid))
|
63
|
+
lvl0_node.descendants.to_a.should eql(descendants)
|
64
|
+
lvl0_node.subtree.to_a.should eql([lvl0_node] + descendants)
|
65
|
+
|
66
|
+
lvl0_children.each do |lvl1_node, lvl1_children|
|
67
|
+
# Ancestors assertions
|
68
|
+
lvl1_node.ancestor_ids.should eql([lvl0_node.uid])
|
69
|
+
lvl1_node.ancestors.to_a.should eql([lvl0_node])
|
70
|
+
lvl1_node.path_ids.should eql([lvl0_node.uid, lvl1_node.uid])
|
71
|
+
lvl1_node.path.to_a.should eql([lvl0_node, lvl1_node])
|
72
|
+
lvl1_node.depth.should eql(1)
|
73
|
+
# Parent assertions
|
74
|
+
lvl1_node.parent_id.should eql(lvl0_node.uid)
|
75
|
+
lvl1_node.parent.should eql(lvl0_node)
|
76
|
+
# Root assertions
|
77
|
+
lvl1_node.root_id.should eql(lvl0_node.uid)
|
78
|
+
lvl1_node.root.should eql(lvl0_node)
|
79
|
+
lvl1_node.is_root?.should be_false
|
80
|
+
# Children assertions
|
81
|
+
lvl1_node.child_ids.should eql(lvl1_children.map(&:first).map(&:uid))
|
82
|
+
lvl1_node.children.to_a.should eql(lvl1_children.map(&:first))
|
83
|
+
lvl1_node.has_children?.should be_true
|
84
|
+
lvl1_node.is_childless?.should be_false
|
85
|
+
# Siblings assertions
|
86
|
+
lvl1_node.sibling_ids.should eql(lvl0_children.map(&:first).map(&:uid))
|
87
|
+
lvl1_node.siblings.to_a.should eql(lvl0_children.map(&:first))
|
88
|
+
lvl1_node.has_siblings?.should be_true
|
89
|
+
lvl1_node.is_only_child?.should be_false
|
90
|
+
# Descendants assertions
|
91
|
+
descendants = model.all.find_all do |node|
|
92
|
+
node.ancestor_ids.include? lvl1_node.uid
|
93
|
+
end
|
94
|
+
|
95
|
+
lvl1_node.descendant_ids.should eql(descendants.map(&:uid))
|
96
|
+
lvl1_node.descendants.to_a.should eql(descendants)
|
97
|
+
lvl1_node.subtree.to_a.should eql([lvl1_node] + descendants)
|
98
|
+
|
99
|
+
lvl1_children.each do |lvl2_node, lvl2_children|
|
100
|
+
# Ancestors assertions
|
101
|
+
lvl2_node.ancestor_ids.should eql([lvl0_node.uid, lvl1_node.uid])
|
102
|
+
lvl2_node.ancestors.to_a.should eql([lvl0_node, lvl1_node])
|
103
|
+
lvl2_node.path_ids.should eql([lvl0_node.uid, lvl1_node.uid, lvl2_node.uid])
|
104
|
+
lvl2_node.path.to_a.should eql([lvl0_node, lvl1_node, lvl2_node])
|
105
|
+
lvl2_node.depth.should eql(2)
|
106
|
+
# Parent assertions
|
107
|
+
lvl2_node.parent_id.should eql(lvl1_node.uid)
|
108
|
+
lvl2_node.parent.should eql(lvl1_node)
|
109
|
+
# Root assertions
|
110
|
+
lvl2_node.root_id.should eql(lvl0_node.uid)
|
111
|
+
lvl2_node.root.should eql(lvl0_node)
|
112
|
+
lvl2_node.is_root?.should be_false
|
113
|
+
# Children assertions
|
114
|
+
lvl2_node.child_ids.should eql([])
|
115
|
+
lvl2_node.children.to_a.should eql([])
|
116
|
+
lvl2_node.has_children?.should be_false
|
117
|
+
lvl2_node.is_childless?.should be_true
|
118
|
+
# Siblings assertions
|
119
|
+
lvl2_node.sibling_ids.should eql(lvl1_children.map(&:first).map(&:uid))
|
120
|
+
lvl2_node.siblings.to_a.should eql(lvl1_children.map(&:first))
|
121
|
+
lvl2_node.has_siblings?.should be_true
|
122
|
+
lvl2_node.is_only_child?.should be_false
|
123
|
+
# Descendants assertions
|
124
|
+
descendants = model.all.find_all do |node|
|
125
|
+
node.ancestor_ids.include? lvl2_node.id
|
126
|
+
end
|
127
|
+
lvl2_node.descendant_ids.should eql(descendants.map(&:uid))
|
128
|
+
lvl2_node.descendants.to_a.should eql(descendants)
|
129
|
+
lvl2_node.subtree.to_a.should eql([lvl2_node] + descendants)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should validate ancestry field" do
|
137
|
+
subject.with_model do |model|
|
138
|
+
node = model.create
|
139
|
+
['3', '10/2', '1/4/30', nil].each do |value|
|
140
|
+
node.send :write_attribute, model.ancestry_field, value
|
141
|
+
node.valid?
|
142
|
+
node.errors[model.ancestry_field].blank?.should be_true
|
143
|
+
end
|
144
|
+
['1/3/', '/2/3', 'a', 'a/b', '-34', '/54'].each do |value|
|
145
|
+
node.send :write_attribute, model.ancestry_field, value
|
146
|
+
node.valid?
|
147
|
+
node.errors[model.ancestry_field].blank?.should be_false
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should move descendants with node" do
|
153
|
+
subject.with_model :depth => 3, :width => 3 do |model, roots|
|
154
|
+
root1, root2, root3 = roots.map(&:first)
|
155
|
+
|
156
|
+
descendants = root1.descendants.asc(:uid).to_a
|
157
|
+
expect {
|
158
|
+
root1.parent = root2
|
159
|
+
root1.save!
|
160
|
+
root1.descendants.asc(:uid).to_a.should eql(descendants)
|
161
|
+
}.to change(root2.descendants, 'size').by(root1.subtree.size)
|
162
|
+
|
163
|
+
descendants = root2.descendants.asc(:uid).to_a
|
164
|
+
expect {
|
165
|
+
root2.parent = root3
|
166
|
+
root2.save!
|
167
|
+
root2.descendants.asc(:uid).to_a.should eql(descendants)
|
168
|
+
}.to change(root3.descendants, 'size').by(root2.subtree.size)
|
169
|
+
|
170
|
+
descendants = root1.descendants.asc(:uid).to_a
|
171
|
+
expect {
|
172
|
+
expect {
|
173
|
+
root1.parent = nil
|
174
|
+
root1.save!
|
175
|
+
root1.descendants.asc(:uid).to_a.should eql(descendants)
|
176
|
+
}.to change(root3.descendants, 'size').by(-root1.subtree.size)
|
177
|
+
}.to change(root2.descendants, 'size').by(-root1.subtree.size)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should validate ancestry exclude self" do
|
182
|
+
subject.with_model do |model|
|
183
|
+
parent = model.create!
|
184
|
+
child = parent.children.create
|
185
|
+
expect { parent.update_attributes! :parent => child }.to raise_error(Mongoid::Errors::Validations)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should have depth caching" do
|
190
|
+
subject.with_model :depth => 3, :width => 3, :cache_depth => true, :depth_cache_field => :depth_cache do |model, roots|
|
191
|
+
roots.each do |lvl0_node, lvl0_children|
|
192
|
+
lvl0_node.depth_cache.should eql(0)
|
193
|
+
lvl0_children.each do |lvl1_node, lvl1_children|
|
194
|
+
lvl1_node.depth_cache.should eql(1)
|
195
|
+
lvl1_children.each do |lvl2_node, lvl2_children|
|
196
|
+
lvl2_node.depth_cache.should eql(2)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should have descendants with depth constraints" do
|
204
|
+
subject.with_model :depth => 4, :width => 4, :cache_depth => true do |model, roots|
|
205
|
+
model.roots.first.descendants(:before_depth => 2).count.should eql(4)
|
206
|
+
model.roots.first.descendants(:to_depth => 2).count.should eql(20)
|
207
|
+
model.roots.first.descendants(:at_depth => 2).count.should eql(16)
|
208
|
+
model.roots.first.descendants(:from_depth => 2).count.should eql(80)
|
209
|
+
model.roots.first.descendants(:after_depth => 2).count.should eql(64)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should have subtree with depth constraints" do
|
214
|
+
subject.with_model :depth => 4, :width => 4, :cache_depth => true do |model, roots|
|
215
|
+
model.roots.first.subtree(:before_depth => 2).count.should eql(5)
|
216
|
+
model.roots.first.subtree(:to_depth => 2).count.should eql(21)
|
217
|
+
model.roots.first.subtree(:at_depth => 2).count.should eql(16)
|
218
|
+
model.roots.first.subtree(:from_depth => 2).count.should eql(80)
|
219
|
+
model.roots.first.subtree(:after_depth => 2).count.should eql(64)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should have ancestors with depth constraints" do
|
224
|
+
subject.with_model :cache_depth => true do |model|
|
225
|
+
node1 = model.create!
|
226
|
+
node2 = node1.children.create
|
227
|
+
node3 = node2.children.create
|
228
|
+
node4 = node3.children.create
|
229
|
+
node5 = node4.children.create
|
230
|
+
leaf = node5.children.create
|
231
|
+
|
232
|
+
leaf.ancestors(:before_depth => -2).to_a.should eql([node1, node2, node3])
|
233
|
+
leaf.ancestors(:to_depth => -2).to_a.should eql([node1, node2, node3, node4])
|
234
|
+
leaf.ancestors(:at_depth => -2).to_a.should eql([node4])
|
235
|
+
leaf.ancestors(:from_depth => -2).to_a.should eql([node4, node5])
|
236
|
+
leaf.ancestors(:after_depth => -2).to_a.should eql([node5])
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
it "should have path with depth constraints" do
|
241
|
+
subject.with_model :cache_depth => true do |model|
|
242
|
+
node1 = model.create!
|
243
|
+
node2 = node1.children.create
|
244
|
+
node3 = node2.children.create
|
245
|
+
node4 = node3.children.create
|
246
|
+
node5 = node4.children.create
|
247
|
+
leaf = node5.children.create
|
248
|
+
|
249
|
+
leaf.path(:before_depth => -2).to_a.should eql([node1, node2, node3])
|
250
|
+
leaf.path(:to_depth => -2).to_a.should eql([node1, node2, node3, node4])
|
251
|
+
leaf.path(:at_depth => -2).to_a.should eql([node4])
|
252
|
+
leaf.path(:from_depth => -2).to_a.should eql([node4, node5, leaf])
|
253
|
+
leaf.path(:after_depth => -2).to_a.should eql([node5, leaf])
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
it "should raise exception on unknown depth field" do
|
258
|
+
subject.with_model :cache_depth => true do |model|
|
259
|
+
expect {
|
260
|
+
model.create!.subtree(:this_is_not_a_valid_depth_option => 42)
|
261
|
+
}.to raise_error(Mongoid::Ancestry::Error)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
|
266
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'mongoid/ancestry/exceptions'
|
4
|
+
|
5
|
+
|
6
|
+
describe MongoidAncestry do
|
7
|
+
|
8
|
+
subject { MongoidAncestry }
|
9
|
+
|
10
|
+
it "should have ancestry fields" do
|
11
|
+
subject.with_model do |model|
|
12
|
+
model.fields['ancestry'].options[:type].should eql(String)
|
13
|
+
model.fields['uid'].options[:type].should eql(Integer)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should have ancestry indexes" do
|
18
|
+
subject.with_model do |model|
|
19
|
+
model.index_options.should have_key(:uid)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should have non default ancestry field" do
|
24
|
+
subject.with_model :ancestry_field => :alternative_ancestry do |model|
|
25
|
+
model.ancestry_field.should eql(:alternative_ancestry)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should set ancestry field" do
|
30
|
+
subject.with_model do |model|
|
31
|
+
model.ancestry_field = :ancestors
|
32
|
+
model.ancestry_field.should eql(:ancestors)
|
33
|
+
model.ancestry_field = :ancestry
|
34
|
+
model.ancestry_field.should eql(:ancestry)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should have default orphan strategy" do
|
39
|
+
subject.with_model do |model|
|
40
|
+
model.orphan_strategy.should eql(:destroy)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should have non default orphan strategy" do
|
45
|
+
subject.with_model :orphan_strategy => :rootify do |model|
|
46
|
+
model.orphan_strategy.should eql(:rootify)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should set orphan strategy" do
|
51
|
+
subject.with_model do |model|
|
52
|
+
model.orphan_strategy = :rootify
|
53
|
+
model.orphan_strategy.should eql(:rootify)
|
54
|
+
model.orphan_strategy = :destroy
|
55
|
+
model.orphan_strategy.should eql(:destroy)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should not set invalid orphan strategy" do
|
60
|
+
subject.with_model do |model|
|
61
|
+
expect {
|
62
|
+
model.orphan_strategy = :non_existent_orphan_strategy
|
63
|
+
}.to raise_error Mongoid::Ancestry::Error
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should setup test nodes" do
|
68
|
+
subject.with_model :depth => 3, :width => 3 do |model, roots|
|
69
|
+
roots.class.should eql(Array)
|
70
|
+
roots.length.should eql(3)
|
71
|
+
roots.each do |node, children|
|
72
|
+
node.class.should eql(model)
|
73
|
+
children.class.should eql(Array)
|
74
|
+
children.length.should eql(3)
|
75
|
+
children.each do |node, children|
|
76
|
+
node.class.should eql(model)
|
77
|
+
children.class.should eql(Array)
|
78
|
+
children.length.should eql(3)
|
79
|
+
children.each do |node, children|
|
80
|
+
node.class.should eql(model)
|
81
|
+
children.class.should eql(Array)
|
82
|
+
children.length.should eql(0)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should have STI support" do
|
90
|
+
subject.with_model :extra_columns => {:type => :string} do |model|
|
91
|
+
subclass1 = Object.const_set 'Subclass1', Class.new(model)
|
92
|
+
(class << subclass1; self; end).send(:define_method, :model_name) do
|
93
|
+
Struct.new(:human, :underscore).new 'Subclass1', 'subclass1'
|
94
|
+
end
|
95
|
+
subclass2 = Object.const_set 'Subclass2', Class.new(model)
|
96
|
+
(class << subclass2; self; end).send(:define_method, :model_name) do
|
97
|
+
Struct.new(:human, :underscore).new 'Subclass1', 'subclass1'
|
98
|
+
end
|
99
|
+
|
100
|
+
node1 = subclass1.create
|
101
|
+
node2 = subclass2.create :parent => node1
|
102
|
+
node3 = subclass1.create :parent => node2
|
103
|
+
node4 = subclass2.create :parent => node3
|
104
|
+
node5 = subclass1.create :parent => node4
|
105
|
+
|
106
|
+
model.all.each do |node|
|
107
|
+
[subclass1, subclass2].include?(node.class).should be_true
|
108
|
+
end
|
109
|
+
|
110
|
+
node1.descendants.map(&:id).should eql([node2.id, node3.id, node4.id, node5.id])
|
111
|
+
node1.subtree.map(&:id).should eql([node1.id, node2.id, node3.id, node4.id, node5.id])
|
112
|
+
node5.ancestors.map(&:id).should eql([node1.id, node2.id, node3.id, node4.id])
|
113
|
+
node5.path.map(&:id).should eql([node1.id, node2.id, node3.id, node4.id, node5.id])
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
require 'mongoid'
|
5
|
+
require 'rspec'
|
6
|
+
|
7
|
+
Mongoid.configure do |config|
|
8
|
+
logger = Logger.new('log/test.log')
|
9
|
+
config.master = Mongo::Connection.new('localhost', 27017,
|
10
|
+
:logger => logger).db('ancestry_test')
|
11
|
+
config.logger = logger
|
12
|
+
end
|
13
|
+
|
14
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
15
|
+
|
16
|
+
RSpec.configure do |config|
|
17
|
+
config.after :each do
|
18
|
+
Mongoid.master.collections.reject { |c| c.name =~ /^system\./ }.each(&:drop)
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'mongoid/ancestry'
|
2
|
+
|
3
|
+
|
4
|
+
class MongoidAncestry
|
5
|
+
|
6
|
+
def self.with_model options = {}
|
7
|
+
depth = options.delete(:depth) || 0
|
8
|
+
width = options.delete(:width) || 0
|
9
|
+
extra_columns = options.delete(:extra_columns)
|
10
|
+
skip_ancestry = options.delete(:skip_ancestry)
|
11
|
+
|
12
|
+
begin
|
13
|
+
model = Class.new
|
14
|
+
(class << model; self; end).send :define_method, :model_name do; Struct.new(:human, :underscore, :i18n_key).new 'TestNode', 'test_node', 'key'; end
|
15
|
+
const_set 'TestNode', model
|
16
|
+
TestNode.send(:include, Mongoid::Document)
|
17
|
+
TestNode.send(:include, Mongoid::Ancestry) unless skip_ancestry
|
18
|
+
|
19
|
+
extra_columns.each do |name, type|
|
20
|
+
TestNode.send :field, name, :type => type.to_s.capitalize.constantize
|
21
|
+
end unless extra_columns.nil?
|
22
|
+
|
23
|
+
TestNode.has_ancestry options unless skip_ancestry
|
24
|
+
|
25
|
+
if depth > 0
|
26
|
+
yield TestNode, create_test_nodes(TestNode, depth, width)
|
27
|
+
else
|
28
|
+
yield TestNode
|
29
|
+
end
|
30
|
+
ensure
|
31
|
+
#Mongoid.master.collections.reject { |c| c.name =~ /^system\./ }.each(&:drop)
|
32
|
+
remove_const "TestNode"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.create_test_nodes model, depth, width, parent = nil
|
37
|
+
unless depth == 0
|
38
|
+
Array.new width do
|
39
|
+
node = model.create!(:parent => parent)
|
40
|
+
[node, create_test_nodes(model, depth - 1, width, node)]
|
41
|
+
end
|
42
|
+
else; []; end
|
43
|
+
end
|
44
|
+
end
|