mm-tree 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/locale/en.yml +1 -1
- data/lib/locale/nb.yml +8 -0
- data/lib/mongo_mapper/plugins/tree.rb +67 -42
- data/lib/version.rb +1 -1
- data/test/helper.rb +32 -0
- data/test/test_search_class_multi.rb +6 -5
- data/test/test_tree.rb +79 -12
- metadata +49 -36
data/lib/locale/en.yml
CHANGED
@@ -5,4 +5,4 @@ en:
|
|
5
5
|
tree:
|
6
6
|
cyclic: "Can't be children of a descendant"
|
7
7
|
incorrect_parent_nv_dv: "Positional values doesn't match parent (check nv/dv values)"
|
8
|
-
search_class_mismatch: "Mismatch between search classes. Parent: %{parent_search_class} Node: %{node_search_class}
|
8
|
+
search_class_mismatch: "Mismatch between search classes. Parent: %{parent_search_class} Node: %{node_search_class}"
|
data/lib/locale/nb.yml
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
nb:
|
2
|
+
mongo_mapper:
|
3
|
+
errors:
|
4
|
+
messages:
|
5
|
+
tree:
|
6
|
+
cyclic: "Kan ikke være barnet av en etterkommer."
|
7
|
+
incorrect_parent_nv_dv: "Posisjonelle/rasjonelle verdier stemmer ikke (check nv/dv values)"
|
8
|
+
search_class_mismatch: "Søke klassene er ikke identiske. Forelder: %{parent_search_class} Node/barn: %{node_search_class}."
|
@@ -12,6 +12,22 @@ module MongoMapper
|
|
12
12
|
self.where(tree_parent_id_field => nil).sort(tree_sort_order()).all
|
13
13
|
end
|
14
14
|
|
15
|
+
# force all keys to update
|
16
|
+
def rekey_all!
|
17
|
+
# rekey keys for each root. will do children
|
18
|
+
_pos = 1
|
19
|
+
self.roots.each do |root|
|
20
|
+
new_keys = keys_from_parent_keys_and_position({:nv => 0, :dv => 1, :snv => 1, :sdv => 0}, _pos)
|
21
|
+
if !compare_keys(root.tree_keys(), new_keys)
|
22
|
+
root.move_nv_dv(new_keys[:nv], new_keys[:dv], {:ignore_conflict => true})
|
23
|
+
root.save!
|
24
|
+
root.reload
|
25
|
+
end
|
26
|
+
root.rekey_children
|
27
|
+
_pos += 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
15
31
|
def position_from_nv_dv(nv, dv)
|
16
32
|
anc_tree_keys = ancestor_tree_keys(nv, dv)
|
17
33
|
(nv - anc_tree_keys[:nv]) / anc_tree_keys[:snv]
|
@@ -51,11 +67,25 @@ module MongoMapper
|
|
51
67
|
return rethash
|
52
68
|
end #get_ancestor_keys(nv,dv)
|
53
69
|
|
70
|
+
def keys_from_parent_keys_and_position(parent_keys, position)
|
71
|
+
{ :nv => parent_keys[:nv] + (position * parent_keys[:snv]),
|
72
|
+
:dv => parent_keys[:dv] + (position * parent_keys[:sdv]),
|
73
|
+
:snv => parent_keys[:nv] + ((position + 1) * parent_keys[:snv]),
|
74
|
+
:sdv => parent_keys[:dv] + ((position + 1) * parent_keys[:sdv]) }
|
75
|
+
end
|
76
|
+
|
77
|
+
def compare_keys(key1, key2)
|
78
|
+
( (key1[:nv] === key2[:nv]) and
|
79
|
+
(key1[:dv] === key2[:dv]) and
|
80
|
+
(key1[:snv] === key2[:snv]) and
|
81
|
+
(key1[:sdv] === key2[:sdv]))
|
82
|
+
end
|
83
|
+
|
54
84
|
def tree_sort_order
|
55
85
|
if !tree_use_rational_numbers
|
56
|
-
"#{tree_order}
|
86
|
+
"#{tree_order} #{tree_info_depth_field}"
|
57
87
|
else
|
58
|
-
|
88
|
+
tree_info_nv_div_dv_field.asc
|
59
89
|
end
|
60
90
|
end
|
61
91
|
|
@@ -85,11 +115,17 @@ module MongoMapper
|
|
85
115
|
self.tree_search_class ||= self
|
86
116
|
|
87
117
|
class_attribute :tree_parent_id_field
|
88
|
-
self.tree_parent_id_field ||=
|
118
|
+
self.tree_parent_id_field ||= :parent_id
|
89
119
|
|
90
120
|
class_attribute :tree_use_rational_numbers
|
91
121
|
self.tree_use_rational_numbers ||= true
|
92
122
|
|
123
|
+
class_attribute :tree_info_depth_field
|
124
|
+
self.tree_info_depth_field ||= :tree_info_depth
|
125
|
+
|
126
|
+
class_attribute :tree_info_nv_div_dv_field
|
127
|
+
self.tree_info_nv_div_dv_field ||= :tree_info_nv_div_dv
|
128
|
+
|
93
129
|
class_attribute :tree_order
|
94
130
|
|
95
131
|
key tree_parent_id_field, ObjectId
|
@@ -139,11 +175,11 @@ module MongoMapper
|
|
139
175
|
if parent.nil?
|
140
176
|
self[tree_parent_id_field] = nil
|
141
177
|
self.tree_info.path = []
|
142
|
-
self
|
178
|
+
self[tree_info_depth_field] = 0
|
143
179
|
elsif !!opts[:force] || self.changes.include?(tree_parent_id_field)
|
144
180
|
@_will_move = true
|
145
181
|
self.tree_info.path = parent.tree_info.path + [parent._id]
|
146
|
-
self
|
182
|
+
self[tree_info_depth_field] = parent[tree_info_depth_field] + 1
|
147
183
|
end
|
148
184
|
end
|
149
185
|
|
@@ -156,8 +192,8 @@ module MongoMapper
|
|
156
192
|
self.tree_info.dv = dv
|
157
193
|
end
|
158
194
|
|
159
|
-
|
160
|
-
|
195
|
+
# Should calculate next free nv/dv and set that if parent has changed.
|
196
|
+
# (set values to "missing and call missing function should work")
|
161
197
|
def update_nv_dv(opts = {})
|
162
198
|
return if !tree_use_rational_numbers
|
163
199
|
if @_set_nv_dv == true
|
@@ -172,9 +208,8 @@ module MongoMapper
|
|
172
208
|
elsif (self.changes.include?(tree_parent_id_field)) || opts[:force]
|
173
209
|
# only changed parent, needs to find next free position
|
174
210
|
# use function for "missing nv/dv"
|
175
|
-
|
176
|
-
new_keys = self.
|
177
|
-
new_keys = self.next_keys_available(self[tree_parent_id_field], (opts[:position] + 1)) if opts[:position]
|
211
|
+
new_keys = self.keys_from_position((self.has_siblings? + 1)) if !opts[:position]
|
212
|
+
new_keys = self.keys_from_position((opts[:position] + 1)) if opts[:position]
|
178
213
|
self.move_nv_dv(new_keys[:nv], new_keys[:dv])
|
179
214
|
end
|
180
215
|
end
|
@@ -193,12 +228,12 @@ module MongoMapper
|
|
193
228
|
else
|
194
229
|
last_sibling_position = self.class.position_from_nv_dv(last_sibling.tree_info.nv, last_sibling.tree_info.dv)
|
195
230
|
end
|
196
|
-
new_keys = self.
|
231
|
+
new_keys = self.keys_from_position((last_sibling_position + 1) )
|
197
232
|
self.tree_info.nv = new_keys[:nv]
|
198
233
|
self.tree_info.dv = new_keys[:dv]
|
199
234
|
self.tree_info.snv = new_keys[:snv]
|
200
235
|
self.tree_info.sdv = new_keys[:sdv]
|
201
|
-
self
|
236
|
+
self[tree_info_nv_div_dv_field] = Float(new_keys[:nv]/Float(new_keys[:dv]))
|
202
237
|
@_set_nv_dv = true
|
203
238
|
end
|
204
239
|
end
|
@@ -208,9 +243,6 @@ module MongoMapper
|
|
208
243
|
# can force move without updating conflicting siblings
|
209
244
|
def move_nv_dv(nv, dv, opts = {})
|
210
245
|
return if !tree_use_rational_numbers
|
211
|
-
# return
|
212
|
-
# nv_div_dv = Float(nv)/Float(dv)
|
213
|
-
# find nv_div_dv?
|
214
246
|
position = self.class.position_from_nv_dv(nv, dv)
|
215
247
|
if !self.root?
|
216
248
|
anc_keys = self.class.ancestor_tree_keys(nv, dv)
|
@@ -240,14 +272,14 @@ module MongoMapper
|
|
240
272
|
self.tree_info.dv = dv
|
241
273
|
self.tree_info.snv = rnv
|
242
274
|
self.tree_info.sdv = rdv
|
243
|
-
self
|
275
|
+
self[tree_info_nv_div_dv_field] = Float(self.tree_info.nv)/Float(self.tree_info.dv)
|
244
276
|
# as this is triggered from after_validation, save should be triggered by the caller.
|
245
277
|
end
|
246
278
|
# change this require ancestor data + position,
|
247
279
|
# next position can be found using: self.has_siblings? + 1
|
248
280
|
# as when moving children, the sibling_count won't work
|
249
|
-
def
|
250
|
-
_parent = tree_search_class.where(:_id =>
|
281
|
+
def keys_from_position(position)
|
282
|
+
_parent = tree_search_class.where(:_id => self[tree_parent_id_field]).first
|
251
283
|
_parent = nil if ((_parent.nil?) || (_parent == []))
|
252
284
|
ancnv = 0
|
253
285
|
ancsnv = 1
|
@@ -259,24 +291,11 @@ module MongoMapper
|
|
259
291
|
ancdv = _parent.tree_info.dv
|
260
292
|
ancsdv = _parent.tree_info.sdv
|
261
293
|
end
|
262
|
-
|
263
|
-
rethash = {:nv => 1, :dv => 1, :snv => 2, :sdv => 1}
|
264
|
-
else
|
265
|
-
# get values from sibling_count
|
266
|
-
_nv = ancnv + (position * ancsnv)
|
267
|
-
_dv = ancdv + (position * ancsdv)
|
268
|
-
rethash = {
|
269
|
-
:nv => _nv,
|
270
|
-
:dv => _dv,
|
271
|
-
:snv => ancnv + ((position + 1) * ancsnv),
|
272
|
-
:sdv => ancdv + ((position + 1) * ancsdv)
|
273
|
-
}
|
274
|
-
end
|
275
|
-
rethash
|
294
|
+
self.class.keys_from_parent_keys_and_position({:nv => ancnv, :dv => ancdv, :snv => ancsnv, :sdv => ancsdv}, position)
|
276
295
|
end
|
277
296
|
|
278
297
|
def next_sibling_keys
|
279
|
-
|
298
|
+
keys_from_position(self.class.position_from_nv_dv(self.tree_info.nv, self.tree_info.dv) +1)
|
280
299
|
end
|
281
300
|
|
282
301
|
# to save queries, this will calculate ancestor tree keys instead of query them
|
@@ -330,6 +349,21 @@ module MongoMapper
|
|
330
349
|
end
|
331
350
|
end
|
332
351
|
|
352
|
+
def rekey_children
|
353
|
+
return if (!self.children?)
|
354
|
+
_pos = 1
|
355
|
+
self.children.each do |child|
|
356
|
+
new_keys = self.class.keys_from_parent_keys_and_position(self.tree_keys(), _pos)
|
357
|
+
if !self.class.compare_keys(child.tree_keys(), new_keys)
|
358
|
+
child.move_nv_dv(new_keys[:nv], new_keys[:dv], {:ignore_conflict => true})
|
359
|
+
child.save!
|
360
|
+
child.reload
|
361
|
+
end
|
362
|
+
child.rekey_children
|
363
|
+
_pos += 1
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
333
367
|
def root?
|
334
368
|
self[tree_parent_id_field].nil?
|
335
369
|
end
|
@@ -416,17 +450,8 @@ module MongoMapper
|
|
416
450
|
self.children.each do |child|
|
417
451
|
child.update_path!
|
418
452
|
child.update_nv_dv!(:position => _position)
|
419
|
-
# puts "Update Child - #{child.name.inspect} #{child.changes.inspect}"
|
420
|
-
# puts "#{child.updated_at.to_f}"
|
421
|
-
child.save
|
422
|
-
child.reload
|
423
|
-
# puts "#{child.updated_at.to_f}"
|
424
453
|
child.save
|
425
454
|
child.reload
|
426
|
-
# puts "#{child.updated_at.to_f}"
|
427
|
-
child.reload
|
428
|
-
# puts "#{child.updated_at.to_f}"
|
429
|
-
|
430
455
|
_position += 1
|
431
456
|
end
|
432
457
|
self.enable_timestamp_callback()
|
data/lib/version.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -41,4 +41,36 @@ class Test::Unit::TestCase
|
|
41
41
|
def eql_arrays?(first, second)
|
42
42
|
first.collect(&:_id).to_set == second.collect(&:_id).to_set
|
43
43
|
end
|
44
|
+
|
45
|
+
custom_matcher :verify_keys do |receiver, matcher, args|
|
46
|
+
testkeys = args[0]
|
47
|
+
matcher.positive_failure_message = "Expected #{receiver.name} to match keys #{testkeys}, but got #{receiver.tree_keys()}"
|
48
|
+
matcher.negative_failure_message = "Expected #{receiver.name} to NOT match keys #{testkeys}, but got #{receiver.tree_keys()}"
|
49
|
+
rkeys = receiver.tree_keys()
|
50
|
+
( (rkeys[:nv] === testkeys[:nv]) and
|
51
|
+
(rkeys[:dv] === testkeys[:dv]) and
|
52
|
+
(rkeys[:snv] === testkeys[:snv]) and
|
53
|
+
(rkeys[:sdv] === testkeys[:sdv]))
|
54
|
+
end
|
55
|
+
|
56
|
+
custom_matcher :verify_order do |receiver, matcher, args|
|
57
|
+
matching_order = args[0]
|
58
|
+
order_from_reciever_ids = Array.new
|
59
|
+
order_from_reciever_names = Array.new
|
60
|
+
receiver.each do |reci|
|
61
|
+
# order_from_reciever_ids << reci._id
|
62
|
+
order_from_reciever_names << reci.name
|
63
|
+
end
|
64
|
+
|
65
|
+
order_from_matching_ids = Array.new
|
66
|
+
order_from_matching_names = Array.new
|
67
|
+
matching_order.each do |matc|
|
68
|
+
# order_from_matching_ids << matc._id
|
69
|
+
order_from_matching_names << matc.name
|
70
|
+
end
|
71
|
+
matcher.positive_failure_message = "Expected order to be #{order_from_matching_names}, but got #{order_from_reciever_names}"
|
72
|
+
matcher.negative_failure_message = "Expected order to be different from #{order_from_matching_names}, but got #{order_from_reciever_names}"
|
73
|
+
receiver == args[0]
|
74
|
+
end
|
75
|
+
|
44
76
|
end
|
@@ -14,7 +14,7 @@ class TestSearchScope < Test::Unit::TestCase
|
|
14
14
|
@cube_1_2 = Cube.create(:name => "Cube 1.2", :parent => @cube_1)
|
15
15
|
@cube_1_2_1 = Cube.create(:name => "Cube 1.2.1", :parent => @cube_1_2)
|
16
16
|
@cube_1_2_2 = Cube.create(:name => "Cube 1.2.2", :parent => @cube_1_2)
|
17
|
-
@
|
17
|
+
@cube_1_2_1_1 = Cube.create(:name => "Cube 1.2.1.1", :parent => @cube_1_2_1)
|
18
18
|
end
|
19
19
|
|
20
20
|
should "return cubes as children of cube_1" do
|
@@ -37,9 +37,10 @@ class TestSearchScope < Test::Unit::TestCase
|
|
37
37
|
@cube_1_2.reload
|
38
38
|
@cube_1_2_1.reload
|
39
39
|
@cube_1_2_2.reload
|
40
|
-
@
|
41
|
-
@cube_1_1.siblings.should
|
42
|
-
@cube_1.descendants.should
|
40
|
+
@cube_1_2_1_1.reload
|
41
|
+
@cube_1_1.siblings.should verify_order(Array[@cube_1_2, @cube_1_2_2])
|
42
|
+
@cube_1.descendants.should verify_order(Array[@cube_1_1, @cube_1_2, @cube_1_2_1, @cube_1_2_1_1, @cube_1_2_2])
|
43
|
+
@cube_1.children.should verify_order(Array[@cube_1_1, @cube_1_2, @cube_1_2_2])
|
43
44
|
end
|
44
45
|
|
45
46
|
should "not return any triangles or cubes descendants of shape_1" do
|
@@ -64,7 +65,7 @@ class TestSearchScope < Test::Unit::TestCase
|
|
64
65
|
@cube_1.errors.count.should == 1 #should have an error
|
65
66
|
@cube_1.errors.each do |attribute, errmsg|
|
66
67
|
attribute.to_s.should == "base"
|
67
|
-
errmsg.should == ("Mismatch between search classes. Parent: Triangle Node: Cube
|
68
|
+
errmsg.should == ("Mismatch between search classes. Parent: Triangle Node: Cube")
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
data/test/test_tree.rb
CHANGED
@@ -8,8 +8,7 @@ class TestMongomapperActsAsTree < Test::Unit::TestCase
|
|
8
8
|
@node_1_2_1 = Category.create(:name => "Node 1.2.1", :parent => @node_1_2)
|
9
9
|
@node_1_2_2 = Category.create(:name => "Node 1.2.2", :parent => @node_1_2)
|
10
10
|
@node_1_3 = Category.create(:name => "Node 1.3", :parent => @node_1)
|
11
|
-
|
12
|
-
@node_2 = Category.create(:name => "Node 2")
|
11
|
+
@node_2 = Category.create(:name => "Node 2")
|
13
12
|
@node_2_1 = Category.create(:name => "Node 2.1", :parent => @node_2)
|
14
13
|
@node_2_2 = Category.create(:name => "Node 2.2", :parent => @node_2)
|
15
14
|
@node_2_3 = Category.create(:name => "Node 2.3", :parent => @node_2)
|
@@ -53,9 +52,9 @@ class TestMongomapperActsAsTree < Test::Unit::TestCase
|
|
53
52
|
end
|
54
53
|
|
55
54
|
should "set depth" do
|
56
|
-
@node_1.
|
57
|
-
@node_1_1.
|
58
|
-
@node_1_2_1.
|
55
|
+
@node_1[Category.tree_info_depth_field].should == 0
|
56
|
+
@node_1_1[Category.tree_info_depth_field].should == 1
|
57
|
+
@node_1_2_1[Category.tree_info_depth_field].should == 2
|
59
58
|
end
|
60
59
|
|
61
60
|
should "have children" do
|
@@ -118,7 +117,7 @@ class TestMongomapperActsAsTree < Test::Unit::TestCase
|
|
118
117
|
assert @node_1_2.descendants.include?(@node_1_3)
|
119
118
|
assert @node_1_2_1.is_or_is_sibling_of?(@node_1_3)
|
120
119
|
assert @node_1_2_2.is_or_is_sibling_of?(@node_1_3)
|
121
|
-
@node_1_3.
|
120
|
+
@node_1_3[Category.tree_info_depth_field].should == 2
|
122
121
|
end
|
123
122
|
|
124
123
|
should "move children on save" do
|
@@ -194,6 +193,26 @@ class TestMongomapperActsAsTree < Test::Unit::TestCase
|
|
194
193
|
end
|
195
194
|
|
196
195
|
context "node (keys)" do
|
196
|
+
should "verify order of tree" do
|
197
|
+
all_category_items = Category.sort(Category.tree_sort_order).all
|
198
|
+
correct_order = Array[@node_1,
|
199
|
+
@node_1_1,
|
200
|
+
@node_1_2,
|
201
|
+
@node_1_2_1,
|
202
|
+
@node_1_2_2,
|
203
|
+
@node_1_3,
|
204
|
+
@node_2,
|
205
|
+
@node_2_1,
|
206
|
+
@node_2_2,
|
207
|
+
@node_2_3,
|
208
|
+
@node_2_4,
|
209
|
+
@node_2_4_1,
|
210
|
+
@node_2_4_1_1,
|
211
|
+
@node_2_4_2,
|
212
|
+
@node_2_4_3]
|
213
|
+
all_category_items.should verify_order(correct_order);
|
214
|
+
end
|
215
|
+
|
197
216
|
should "find keys from id" do
|
198
217
|
assert Category.find(@node_1._id).tree_keys == @node_1.tree_keys, "Query doesn't match created object #{@node_1.name}"
|
199
218
|
assert Category.find(@node_2_4_1_1._id).tree_keys == @node_2_4_1_1.tree_keys, "Query doesn't match created object #{@node_2_4_1_1.name}"
|
@@ -236,7 +255,7 @@ class TestMongomapperActsAsTree < Test::Unit::TestCase
|
|
236
255
|
|
237
256
|
should "move to new specific nv, dv location and move conflicting items" do
|
238
257
|
assert @node_2_4.ancestor_tree_keys() == @node_2.tree_keys(), "Before move: #{@node_2_4.name} ancestor keys should match #{@node_2.name} got: #{@node_2_4.ancestor_tree_keys()} expected: #{@node_2.tree_keys()}"
|
239
|
-
assert @node_2_4_1.
|
258
|
+
assert @node_2_4_1[Category.tree_info_depth_field] == 2, "Before move: Depth of #{@node_2_4_1.name} should be 2"
|
240
259
|
old_1_2_keys = @node_1_2.tree_keys()
|
241
260
|
new_node_1_2_keys = @node_1_2.next_sibling_keys
|
242
261
|
@node_2_4.set_position(@node_1_2.tree_info.nv, @node_1_2.tree_info.dv)
|
@@ -253,7 +272,7 @@ class TestMongomapperActsAsTree < Test::Unit::TestCase
|
|
253
272
|
|
254
273
|
should "move @node_2_4 to root position" do
|
255
274
|
assert @node_2_4.ancestor_tree_keys() == @node_2.tree_keys(), "Before move: #{@node_2_4.name} ancestor keys should match #{@node_2.name} got: #{@node_2_4.ancestor_tree_keys()} expected: #{@node_2.tree_keys()}"
|
256
|
-
assert @node_2_4_1.
|
275
|
+
assert @node_2_4_1[Category.tree_info_depth_field] == 2, "Before move: Depth of #{@node_2_4_1.name} should be 2"
|
257
276
|
@node_2_4.parent = nil
|
258
277
|
@node_2_4.save
|
259
278
|
@node_2_4.reload
|
@@ -263,7 +282,7 @@ class TestMongomapperActsAsTree < Test::Unit::TestCase
|
|
263
282
|
# TODO: OVERRIDE RELOAD TO LOAD ALL CHILDREN IN MEMORY/CACHE/ASSOCS
|
264
283
|
@node_2_4_1.reload
|
265
284
|
assert @node_2_4_1.tree_info.path.count == 1, "After move: Path length of #{@node_2_4_1.name} should only be 1"
|
266
|
-
assert @node_2_4_1.
|
285
|
+
assert @node_2_4_1[Category.tree_info_depth_field] == 1, "After move: Depth of #{@node_2_4_1.name} should be 1"
|
267
286
|
assert @node_2_4_1.ancestor_tree_keys() == @node_2_4.tree_keys(), "After move: #{@node_2_4_1.name} ancestor keys should match #{@node_2_4.name} got: #{@node_2_4_1.ancestor_tree_keys()} expected: #{@node_2_4.tree_keys()}"
|
268
287
|
# TODO: OVERRIDE RELOAD TO LOAD ALL CHILDREN IN MEMORY/CACHE/ASSOCS
|
269
288
|
@node_2_4_1_1.reload
|
@@ -295,11 +314,59 @@ class TestMongomapperActsAsTree < Test::Unit::TestCase
|
|
295
314
|
node_1_4.tree_keys.should_not == Hash[:nv => 7, :dv => 4, :snv => 9, :sdv => 5]
|
296
315
|
node_1_4.tree_keys.should == Hash[:nv => 9, :dv => 5, :snv => 11, :sdv => 6]
|
297
316
|
end
|
298
|
-
end # tree keys
|
299
317
|
|
300
|
-
|
301
|
-
|
318
|
+
end # context "node (keys)" do
|
319
|
+
context "when rekeying" do
|
320
|
+
should "be able to update the entire treestructre" do
|
321
|
+
return true
|
322
|
+
old_keys_node_1_2 = @node_1_2.tree_keys()
|
323
|
+
old_keys_node_2_4_2 = @node_2_4_2.tree_keys()
|
324
|
+
@node_1_2.destroy
|
325
|
+
@node_2_4_2.destroy
|
326
|
+
Category.rekey_all!
|
327
|
+
|
328
|
+
# verify some nodes that should be unaffected by rekeying
|
329
|
+
@node_1.reload
|
330
|
+
@node_2.reload
|
331
|
+
@node_2_1.reload
|
332
|
+
@node_1.should verify_keys(Hash[:nv => 1, :dv => 1, :snv => 2, :sdv => 1])
|
333
|
+
@node_2.should verify_keys(Hash[:nv => 2, :dv => 1, :snv => 3, :sdv => 1])
|
334
|
+
@node_2_1.should verify_keys(Hash[:nv => 5, :dv => 2, :snv => 8, :sdv => 3])
|
335
|
+
|
336
|
+
@node_1_3.reload
|
337
|
+
@node_2_4_3.reload
|
338
|
+
@node_1_3.should verify_keys(old_keys_node_1_2)
|
339
|
+
@node_2_4_3.should verify_keys(old_keys_node_2_4_2)
|
340
|
+
end
|
341
|
+
|
342
|
+
should "rekey descendants of node_2" do
|
343
|
+
_node_2_2_1 = Category.create(:name => "Node 2.2.1", :parent => @node_2_2)
|
344
|
+
_node_2_2_1_1 = Category.create(:name => "Node 2.2.1.1", :parent => _node_2_2_1)
|
345
|
+
old_keys_node_2_4_1_1 = @node_2_4_1_1.tree_keys()
|
346
|
+
old_keys_node_2_4_1 = @node_2_4_1.tree_keys()
|
347
|
+
old_keys_node_2_2 = @node_2_2.tree_keys()
|
348
|
+
old_keys_node_2_2_1_1 = _node_2_2_1_1.tree_keys()
|
349
|
+
old_keys_node_2_2_1 = _node_2_2_1.tree_keys()
|
350
|
+
_node_2_2_1.destroy # delete temporary node
|
351
|
+
@node_2_2.destroy
|
352
|
+
@node_2_3.destroy
|
353
|
+
@node_2.rekey_children()
|
354
|
+
@node_2_4.reload
|
355
|
+
@node_2_4_1.reload
|
356
|
+
@node_2_4_1_1.reload
|
357
|
+
|
358
|
+
# verify some nodes that should be unaffected by rekeying
|
359
|
+
@node_1.reload
|
360
|
+
@node_1.should verify_keys(Hash[:nv => 1, :dv => 1, :snv => 2, :sdv => 1])
|
361
|
+
@node_2_4.should verify_keys(old_keys_node_2_2)
|
362
|
+
@node_2_4_1.should_not verify_keys(old_keys_node_2_4_1)
|
363
|
+
@node_2_4_1_1.should_not verify_keys(old_keys_node_2_4_1_1)
|
364
|
+
@node_2_4_1.should verify_keys(old_keys_node_2_2_1)
|
365
|
+
@node_2_4_1_1.should verify_keys(old_keys_node_2_2_1_1)
|
366
|
+
end
|
367
|
+
|
302
368
|
end
|
303
369
|
|
370
|
+
|
304
371
|
end #Context "Tree" do
|
305
372
|
end
|
metadata
CHANGED
@@ -1,40 +1,50 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: mm-tree
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 31
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 2
|
10
|
+
version: 0.1.2
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Leif Ringstad
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ~>
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: 0.11.2
|
17
|
+
|
18
|
+
date: 2012-09-02 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
22
21
|
type: :runtime
|
23
|
-
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
23
|
none: false
|
26
|
-
requirements:
|
24
|
+
requirements:
|
27
25
|
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
hash: 55
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
- 11
|
31
|
+
- 2
|
29
32
|
version: 0.11.2
|
33
|
+
version_requirements: *id001
|
34
|
+
prerelease: false
|
35
|
+
name: mongo_mapper
|
30
36
|
description: Tree structure for MongoMapper with rational number sorting
|
31
|
-
email:
|
37
|
+
email:
|
32
38
|
- leifcr@gmail.com
|
33
39
|
executables: []
|
40
|
+
|
34
41
|
extensions: []
|
42
|
+
|
35
43
|
extra_rdoc_files: []
|
36
|
-
|
44
|
+
|
45
|
+
files:
|
37
46
|
- lib/locale/en.yml
|
47
|
+
- lib/locale/nb.yml
|
38
48
|
- lib/mm-tree.rb
|
39
49
|
- lib/mongo_mapper/plugins/tree.rb
|
40
50
|
- lib/mongo_mapper/plugins/tree_info.rb
|
@@ -51,35 +61,38 @@ files:
|
|
51
61
|
- README.rdoc
|
52
62
|
homepage: http://github.com/leifcr/mm-tree
|
53
63
|
licenses: []
|
64
|
+
|
54
65
|
post_install_message:
|
55
66
|
rdoc_options: []
|
56
|
-
|
67
|
+
|
68
|
+
require_paths:
|
57
69
|
- lib
|
58
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
71
|
none: false
|
60
|
-
requirements:
|
61
|
-
- -
|
62
|
-
- !ruby/object:Gem::Version
|
63
|
-
|
64
|
-
segments:
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 3
|
76
|
+
segments:
|
65
77
|
- 0
|
66
|
-
|
67
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
version: "0"
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
80
|
none: false
|
69
|
-
requirements:
|
70
|
-
- -
|
71
|
-
- !ruby/object:Gem::Version
|
72
|
-
|
73
|
-
segments:
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
hash: 3
|
85
|
+
segments:
|
74
86
|
- 0
|
75
|
-
|
87
|
+
version: "0"
|
76
88
|
requirements: []
|
89
|
+
|
77
90
|
rubyforge_project:
|
78
91
|
rubygems_version: 1.8.24
|
79
92
|
signing_key:
|
80
93
|
specification_version: 3
|
81
94
|
summary: Tree structure for MongoMapper
|
82
|
-
test_files:
|
95
|
+
test_files:
|
83
96
|
- test/helper.rb
|
84
97
|
- test/models/category.rb
|
85
98
|
- test/models/ordered_category.rb
|