awesome_nested_set_jrmurad 1.4.3

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.
@@ -0,0 +1,32 @@
1
+ module CollectiveIdea #:nodoc:
2
+ module Acts #:nodoc:
3
+ module NestedSet #:nodoc:
4
+ # This module provides some helpers for the model classes using acts_as_nested_set.
5
+ # It is included by default in all views.
6
+ #
7
+ module Helper
8
+ # Returns options for select.
9
+ # You can exclude some items from the tree.
10
+ # You can pass a block receiving an item and returning the string displayed in the select.
11
+ #
12
+ # == Params
13
+ # * +class_or_item+ - Class name or top level times
14
+ # * +mover+ - The item that is being move, used to exlude impossible moves
15
+ # * +&block+ - a block that will be used to display: { |item, descendants, level| ... }
16
+ #
17
+ # == Usage
18
+ #
19
+ # <%= f.select :parent_id, nested_set_options(Category, @category) { |item, descendants, level|
20
+ # "#{'–' * level} #{item.name}"
21
+ # }) %>
22
+ #
23
+ def nested_set_options(class_or_item, mover = nil, &block)
24
+ class_or_item.traverse(true, mover) do |item, descendants, level|
25
+ [ block.call(item, descendants, level), item.id ]
26
+ end
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1 @@
1
+ # This file is here to satisfy test_help from Rails < 2.3
@@ -0,0 +1,41 @@
1
+ require 'test_helper'
2
+
3
+ module CollectiveIdea
4
+ module Acts #:nodoc:
5
+ module NestedSet #:nodoc:
6
+ class AwesomeNestedSetTest < TestCaseClass
7
+ include Helper
8
+ fixtures :categories
9
+
10
+ def test_nested_set_options
11
+ expected = [
12
+ [" Top Level", 1],
13
+ ["- Child 1", 2],
14
+ ['- Child 2', 3],
15
+ ['-- Child 2.1', 4],
16
+ ['- Child 3', 5],
17
+ [" Top Level 2", 6]
18
+ ]
19
+ actual = nested_set_options(Category) do |c,d,level|
20
+ "#{'-' * level} #{c.name}"
21
+ end
22
+ assert_equal expected, actual
23
+ end
24
+
25
+ def test_nested_set_options_with_mover
26
+ expected = [
27
+ [" Top Level", 1],
28
+ ["- Child 1", 2],
29
+ ['- Child 3', 5],
30
+ [" Top Level 2", 6]
31
+ ]
32
+ actual = nested_set_options(Category, categories(:child_2)) do |c,d,level|
33
+ "#{'-' * level} #{c.name}"
34
+ end
35
+ assert_equal expected, actual
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,801 @@
1
+ require 'test_helper'
2
+
3
+ class Note < ActiveRecord::Base
4
+ acts_as_nested_set :scope => [:notable_id, :notable_type]
5
+ end
6
+ class Default < ActiveRecord::Base
7
+ acts_as_nested_set
8
+ set_table_name 'categories'
9
+ end
10
+ class ScopedCategory < ActiveRecord::Base
11
+ acts_as_nested_set :scope => :organization
12
+ set_table_name 'categories'
13
+ end
14
+ class RenamedColumns < ActiveRecord::Base
15
+ acts_as_nested_set :parent_column => 'mother_id', :left_column => 'red', :right_column => 'black'
16
+ end
17
+
18
+ class AwesomeNestedSetTest < TestCaseClass
19
+
20
+ def test_left_column_default
21
+ assert_equal 'lft', Default.acts_as_nested_set_options[:left_column]
22
+ end
23
+
24
+ def test_right_column_default
25
+ assert_equal 'rgt', Default.acts_as_nested_set_options[:right_column]
26
+ end
27
+
28
+ def test_parent_column_default
29
+ assert_equal 'parent_id', Default.acts_as_nested_set_options[:parent_column]
30
+ end
31
+
32
+ def test_scope_default
33
+ assert_nil Default.acts_as_nested_set_options[:scope]
34
+ end
35
+
36
+ def test_left_column_name
37
+ assert_equal 'lft', Default.left_column_name
38
+ assert_equal 'lft', Default.new.left_column_name
39
+ assert_equal 'red', RenamedColumns.left_column_name
40
+ assert_equal 'red', RenamedColumns.new.left_column_name
41
+ end
42
+
43
+ def test_right_column_name
44
+ assert_equal 'rgt', Default.right_column_name
45
+ assert_equal 'rgt', Default.new.right_column_name
46
+ assert_equal 'black', RenamedColumns.right_column_name
47
+ assert_equal 'black', RenamedColumns.new.right_column_name
48
+ end
49
+
50
+ def test_parent_column_name
51
+ assert_equal 'parent_id', Default.parent_column_name
52
+ assert_equal 'parent_id', Default.new.parent_column_name
53
+ assert_equal 'mother_id', RenamedColumns.parent_column_name
54
+ assert_equal 'mother_id', RenamedColumns.new.parent_column_name
55
+ end
56
+
57
+ def test_creation_with_altered_column_names
58
+ assert_nothing_raised do
59
+ RenamedColumns.create!()
60
+ end
61
+ end
62
+
63
+ def test_quoted_left_column_name
64
+ quoted = Default.connection.quote_column_name('lft')
65
+ assert_equal quoted, Default.quoted_left_column_name
66
+ assert_equal quoted, Default.new.quoted_left_column_name
67
+ end
68
+
69
+ def test_quoted_right_column_name
70
+ quoted = Default.connection.quote_column_name('rgt')
71
+ assert_equal quoted, Default.quoted_right_column_name
72
+ assert_equal quoted, Default.new.quoted_right_column_name
73
+ end
74
+
75
+ def test_left_column_protected_from_assignment
76
+ assert_raises(ActiveRecord::ActiveRecordError) { Category.new.lft = 1 }
77
+ end
78
+
79
+ def test_right_column_protected_from_assignment
80
+ assert_raises(ActiveRecord::ActiveRecordError) { Category.new.rgt = 1 }
81
+ end
82
+
83
+ def test_colums_protected_on_initialize
84
+ c = Category.new(:lft => 1, :rgt => 2)
85
+ assert_nil c.lft
86
+ assert_nil c.rgt
87
+ end
88
+
89
+ def test_scoped_appends_id
90
+ assert_equal :organization_id, ScopedCategory.acts_as_nested_set_options[:scope]
91
+ end
92
+
93
+ def test_roots_class_method
94
+ assert_equal Category.find_all_by_parent_id(nil), Category.roots
95
+ end
96
+
97
+ def test_root_class_method
98
+ assert_equal categories(:top_level), Category.root
99
+ end
100
+
101
+ def test_root
102
+ assert_equal categories(:top_level), categories(:child_3).root
103
+ end
104
+
105
+ def test_root?
106
+ assert categories(:top_level).root?
107
+ assert categories(:top_level_2).root?
108
+ end
109
+
110
+ def test_leaves_class_method
111
+ assert_equal Category.find(:all, :conditions => "#{Category.right_column_name} - #{Category.left_column_name} = 1"), Category.leaves
112
+ assert_equal Category.leaves.count, 4
113
+ assert (Category.leaves.include? categories(:child_1))
114
+ assert (Category.leaves.include? categories(:child_2_1))
115
+ assert (Category.leaves.include? categories(:child_3))
116
+ assert (Category.leaves.include? categories(:top_level_2))
117
+ end
118
+
119
+ def test_leaf
120
+ assert categories(:child_1).leaf?
121
+ assert categories(:child_2_1).leaf?
122
+ assert categories(:child_3).leaf?
123
+ assert categories(:top_level_2).leaf?
124
+
125
+ assert !categories(:top_level).leaf?
126
+ assert !categories(:child_2).leaf?
127
+ assert !Category.new.leaf?
128
+ end
129
+
130
+
131
+ def test_parent
132
+ assert_equal categories(:child_2), categories(:child_2_1).parent
133
+ end
134
+
135
+ def test_self_and_ancestors
136
+ child = categories(:child_2_1)
137
+ self_and_ancestors = [categories(:top_level), categories(:child_2), child]
138
+ assert_equal self_and_ancestors, child.self_and_ancestors
139
+ end
140
+
141
+ def test_ancestors
142
+ child = categories(:child_2_1)
143
+ ancestors = [categories(:top_level), categories(:child_2)]
144
+ assert_equal ancestors, child.ancestors
145
+ end
146
+
147
+ def test_self_and_siblings
148
+ child = categories(:child_2)
149
+ self_and_siblings = [categories(:child_1), child, categories(:child_3)]
150
+ assert_equal self_and_siblings, child.self_and_siblings
151
+ assert_nothing_raised do
152
+ tops = [categories(:top_level), categories(:top_level_2)]
153
+ assert_equal tops, categories(:top_level).self_and_siblings
154
+ end
155
+ end
156
+
157
+ def test_siblings
158
+ child = categories(:child_2)
159
+ siblings = [categories(:child_1), categories(:child_3)]
160
+ assert_equal siblings, child.siblings
161
+ end
162
+
163
+ def test_leaves
164
+ leaves = [categories(:child_1), categories(:child_2_1), categories(:child_3), categories(:top_level_2)]
165
+ assert categories(:top_level).leaves, leaves
166
+ end
167
+
168
+ def test_level
169
+ assert_equal 0, categories(:top_level).level
170
+ assert_equal 1, categories(:child_1).level
171
+ assert_equal 2, categories(:child_2_1).level
172
+ end
173
+
174
+ def test_has_children?
175
+ assert categories(:child_2_1).children.empty?
176
+ assert !categories(:child_2).children.empty?
177
+ assert !categories(:top_level).children.empty?
178
+ end
179
+
180
+ def test_self_and_descendents
181
+ parent = categories(:top_level)
182
+ self_and_descendants = [parent, categories(:child_1), categories(:child_2),
183
+ categories(:child_2_1), categories(:child_3)]
184
+ assert_equal self_and_descendants, parent.self_and_descendants
185
+ assert_equal self_and_descendants, parent.self_and_descendants.count
186
+ end
187
+
188
+ def test_descendents
189
+ lawyers = Category.create!(:name => "lawyers")
190
+ us = Category.create!(:name => "United States")
191
+ us.move_to_child_of(lawyers)
192
+ patent = Category.create!(:name => "Patent Law")
193
+ patent.move_to_child_of(us)
194
+ lawyers.reload
195
+
196
+ assert_equal 1, lawyers.children.size
197
+ assert_equal 1, us.children.size
198
+ assert_equal 2, lawyers.descendants.size
199
+ end
200
+
201
+ def test_self_and_descendents
202
+ parent = categories(:top_level)
203
+ descendants = [categories(:child_1), categories(:child_2),
204
+ categories(:child_2_1), categories(:child_3)]
205
+ assert_equal descendants, parent.descendants
206
+ end
207
+
208
+ def test_children
209
+ category = categories(:top_level)
210
+ category.children.each {|c| assert_equal category.id, c.parent_id }
211
+ end
212
+
213
+ def test_order_of_children
214
+ categories(:child_2).move_left
215
+ assert_equal categories(:child_2), categories(:top_level).children[0]
216
+ assert_equal categories(:child_1), categories(:top_level).children[1]
217
+ assert_equal categories(:child_3), categories(:top_level).children[2]
218
+ end
219
+
220
+ def test_is_or_is_ancestor_of?
221
+ assert categories(:top_level).is_or_is_ancestor_of?(categories(:child_1))
222
+ assert categories(:top_level).is_or_is_ancestor_of?(categories(:child_2_1))
223
+ assert categories(:child_2).is_or_is_ancestor_of?(categories(:child_2_1))
224
+ assert !categories(:child_2_1).is_or_is_ancestor_of?(categories(:child_2))
225
+ assert !categories(:child_1).is_or_is_ancestor_of?(categories(:child_2))
226
+ assert categories(:child_1).is_or_is_ancestor_of?(categories(:child_1))
227
+ end
228
+
229
+ def test_is_ancestor_of?
230
+ assert categories(:top_level).is_ancestor_of?(categories(:child_1))
231
+ assert categories(:top_level).is_ancestor_of?(categories(:child_2_1))
232
+ assert categories(:child_2).is_ancestor_of?(categories(:child_2_1))
233
+ assert !categories(:child_2_1).is_ancestor_of?(categories(:child_2))
234
+ assert !categories(:child_1).is_ancestor_of?(categories(:child_2))
235
+ assert !categories(:child_1).is_ancestor_of?(categories(:child_1))
236
+ end
237
+
238
+ def test_is_or_is_ancestor_of_with_scope
239
+ root = ScopedCategory.root
240
+ child = root.children.first
241
+ assert root.is_or_is_ancestor_of?(child)
242
+ child.update_attribute :organization_id, 'different'
243
+ assert !root.is_or_is_ancestor_of?(child)
244
+ end
245
+
246
+ def test_is_or_is_descendant_of?
247
+ assert categories(:child_1).is_or_is_descendant_of?(categories(:top_level))
248
+ assert categories(:child_2_1).is_or_is_descendant_of?(categories(:top_level))
249
+ assert categories(:child_2_1).is_or_is_descendant_of?(categories(:child_2))
250
+ assert !categories(:child_2).is_or_is_descendant_of?(categories(:child_2_1))
251
+ assert !categories(:child_2).is_or_is_descendant_of?(categories(:child_1))
252
+ assert categories(:child_1).is_or_is_descendant_of?(categories(:child_1))
253
+ end
254
+
255
+ def test_is_descendant_of?
256
+ assert categories(:child_1).is_descendant_of?(categories(:top_level))
257
+ assert categories(:child_2_1).is_descendant_of?(categories(:top_level))
258
+ assert categories(:child_2_1).is_descendant_of?(categories(:child_2))
259
+ assert !categories(:child_2).is_descendant_of?(categories(:child_2_1))
260
+ assert !categories(:child_2).is_descendant_of?(categories(:child_1))
261
+ assert !categories(:child_1).is_descendant_of?(categories(:child_1))
262
+ end
263
+
264
+ def test_is_or_is_descendant_of_with_scope
265
+ root = ScopedCategory.root
266
+ child = root.children.first
267
+ assert child.is_or_is_descendant_of?(root)
268
+ child.update_attribute :organization_id, 'different'
269
+ assert !child.is_or_is_descendant_of?(root)
270
+ end
271
+
272
+ def test_same_scope?
273
+ root = ScopedCategory.root
274
+ child = root.children.first
275
+ assert child.same_scope?(root)
276
+ child.update_attribute :organization_id, 'different'
277
+ assert !child.same_scope?(root)
278
+ end
279
+
280
+ def test_left_sibling
281
+ assert_equal categories(:child_1), categories(:child_2).left_sibling
282
+ assert_equal categories(:child_2), categories(:child_3).left_sibling
283
+ end
284
+
285
+ def test_left_sibling_of_root
286
+ assert_nil categories(:top_level).left_sibling
287
+ end
288
+
289
+ def test_left_sibling_without_siblings
290
+ assert_nil categories(:child_2_1).left_sibling
291
+ end
292
+
293
+ def test_left_sibling_of_leftmost_node
294
+ assert_nil categories(:child_1).left_sibling
295
+ end
296
+
297
+ def test_right_sibling
298
+ assert_equal categories(:child_3), categories(:child_2).right_sibling
299
+ assert_equal categories(:child_2), categories(:child_1).right_sibling
300
+ end
301
+
302
+ def test_right_sibling_of_root
303
+ assert_equal categories(:top_level_2), categories(:top_level).right_sibling
304
+ assert_nil categories(:top_level_2).right_sibling
305
+ end
306
+
307
+ def test_right_sibling_without_siblings
308
+ assert_nil categories(:child_2_1).right_sibling
309
+ end
310
+
311
+ def test_right_sibling_of_rightmost_node
312
+ assert_nil categories(:child_3).right_sibling
313
+ end
314
+
315
+ def test_move_left
316
+ categories(:child_2).move_left
317
+ assert_nil categories(:child_2).left_sibling
318
+ assert_equal categories(:child_1), categories(:child_2).right_sibling
319
+ assert Category.valid?
320
+ end
321
+
322
+ def test_move_right
323
+ categories(:child_2).move_right
324
+ assert_nil categories(:child_2).right_sibling
325
+ assert_equal categories(:child_3), categories(:child_2).left_sibling
326
+ assert Category.valid?
327
+ end
328
+
329
+ def test_move_to_left_of
330
+ categories(:child_3).move_to_left_of(categories(:child_1))
331
+ assert_nil categories(:child_3).left_sibling
332
+ assert_equal categories(:child_1), categories(:child_3).right_sibling
333
+ assert Category.valid?
334
+ end
335
+
336
+ def test_move_to_right_of
337
+ categories(:child_1).move_to_right_of(categories(:child_3))
338
+ assert_nil categories(:child_1).right_sibling
339
+ assert_equal categories(:child_3), categories(:child_1).left_sibling
340
+ assert Category.valid?
341
+ end
342
+
343
+ def test_move_to_root
344
+ categories(:child_2).move_to_root
345
+ assert_nil categories(:child_2).parent
346
+ assert_equal 0, categories(:child_2).level
347
+ assert_equal 1, categories(:child_2_1).level
348
+ assert_equal 1, categories(:child_2).left
349
+ assert_equal 4, categories(:child_2).right
350
+ assert Category.valid?
351
+ end
352
+
353
+ def test_move_to_child_of
354
+ categories(:child_1).move_to_child_of(categories(:child_3))
355
+ assert_equal categories(:child_3).id, categories(:child_1).parent_id
356
+ assert Category.valid?
357
+ end
358
+
359
+ def test_move_to_child_of_appends_to_end
360
+ child = Category.create! :name => 'New Child'
361
+ child.move_to_child_of categories(:top_level)
362
+ assert_equal child, categories(:top_level).children.last
363
+ end
364
+
365
+ def test_subtree_move_to_child_of
366
+ assert_equal 4, categories(:child_2).left
367
+ assert_equal 7, categories(:child_2).right
368
+
369
+ assert_equal 2, categories(:child_1).left
370
+ assert_equal 3, categories(:child_1).right
371
+
372
+ categories(:child_2).move_to_child_of(categories(:child_1))
373
+ assert Category.valid?
374
+ assert_equal categories(:child_1).id, categories(:child_2).parent_id
375
+
376
+ assert_equal 3, categories(:child_2).left
377
+ assert_equal 6, categories(:child_2).right
378
+ assert_equal 2, categories(:child_1).left
379
+ assert_equal 7, categories(:child_1).right
380
+ end
381
+
382
+ def test_slightly_difficult_move_to_child_of
383
+ assert_equal 11, categories(:top_level_2).left
384
+ assert_equal 12, categories(:top_level_2).right
385
+
386
+ # create a new top-level node and move single-node top-level tree inside it.
387
+ new_top = Category.create(:name => 'New Top')
388
+ assert_equal 13, new_top.left
389
+ assert_equal 14, new_top.right
390
+
391
+ categories(:top_level_2).move_to_child_of(new_top)
392
+
393
+ assert Category.valid?
394
+ assert_equal new_top.id, categories(:top_level_2).parent_id
395
+
396
+ assert_equal 12, categories(:top_level_2).left
397
+ assert_equal 13, categories(:top_level_2).right
398
+ assert_equal 11, new_top.left
399
+ assert_equal 14, new_top.right
400
+ end
401
+
402
+ def test_difficult_move_to_child_of
403
+ assert_equal 1, categories(:top_level).left
404
+ assert_equal 10, categories(:top_level).right
405
+ assert_equal 5, categories(:child_2_1).left
406
+ assert_equal 6, categories(:child_2_1).right
407
+
408
+ # create a new top-level node and move an entire top-level tree inside it.
409
+ new_top = Category.create(:name => 'New Top')
410
+ categories(:top_level).move_to_child_of(new_top)
411
+ categories(:child_2_1).reload
412
+ assert Category.valid?
413
+ assert_equal new_top.id, categories(:top_level).parent_id
414
+
415
+ assert_equal 4, categories(:top_level).left
416
+ assert_equal 13, categories(:top_level).right
417
+ assert_equal 8, categories(:child_2_1).left
418
+ assert_equal 9, categories(:child_2_1).right
419
+ end
420
+
421
+ #rebuild swaps the position of the 2 children when added using move_to_child twice onto same parent
422
+ def test_move_to_child_more_than_once_per_parent_rebuild
423
+ root1 = Category.create(:name => 'Root1')
424
+ root2 = Category.create(:name => 'Root2')
425
+ root3 = Category.create(:name => 'Root3')
426
+
427
+ root2.move_to_child_of root1
428
+ root3.move_to_child_of root1
429
+
430
+ output = Category.roots.last.to_text
431
+ Category.update_all('lft = null, rgt = null')
432
+ Category.rebuild!
433
+
434
+ assert_equal Category.roots.last.to_text, output
435
+ end
436
+
437
+ # doing move_to_child twice onto same parent from the furthest right first
438
+ def test_move_to_child_more_than_once_per_parent_outside_in
439
+ node1 = Category.create(:name => 'Node-1')
440
+ node2 = Category.create(:name => 'Node-2')
441
+ node3 = Category.create(:name => 'Node-3')
442
+
443
+ node2.move_to_child_of node1
444
+ node3.move_to_child_of node1
445
+
446
+ output = Category.roots.last.to_text
447
+ Category.update_all('lft = null, rgt = null')
448
+ Category.rebuild!
449
+
450
+ assert_equal Category.roots.last.to_text, output
451
+ end
452
+
453
+
454
+ def test_valid_with_null_lefts
455
+ assert Category.valid?
456
+ Category.update_all('lft = null')
457
+ assert !Category.valid?
458
+ end
459
+
460
+ def test_valid_with_null_rights
461
+ assert Category.valid?
462
+ Category.update_all('rgt = null')
463
+ assert !Category.valid?
464
+ end
465
+
466
+ def test_valid_with_missing_intermediate_node
467
+ # Even though child_2_1 will still exist, it is a sign of a sloppy delete, not an invalid tree.
468
+ assert Category.valid?
469
+ Category.delete(categories(:child_2).id)
470
+ assert Category.valid?
471
+ end
472
+
473
+ def test_valid_with_overlapping_and_rights
474
+ assert Category.valid?
475
+ categories(:top_level_2)['lft'] = 0
476
+ categories(:top_level_2).save
477
+ assert !Category.valid?
478
+ end
479
+
480
+ def test_rebuild
481
+ assert Category.valid?
482
+ before_text = Category.root.to_text
483
+ Category.update_all('lft = null, rgt = null')
484
+ Category.rebuild!
485
+ assert Category.valid?
486
+ assert_equal before_text, Category.root.to_text
487
+ end
488
+
489
+ def test_move_possible_for_sibling
490
+ assert categories(:child_2).move_possible?(categories(:child_1))
491
+ end
492
+
493
+ def test_move_not_possible_to_self
494
+ assert !categories(:top_level).move_possible?(categories(:top_level))
495
+ end
496
+
497
+ def test_move_not_possible_to_parent
498
+ categories(:top_level).descendants.each do |descendant|
499
+ assert !categories(:top_level).move_possible?(descendant)
500
+ assert descendant.move_possible?(categories(:top_level))
501
+ end
502
+ end
503
+
504
+ def test_is_or_is_ancestor_of?
505
+ [:child_1, :child_2, :child_2_1, :child_3].each do |c|
506
+ assert categories(:top_level).is_or_is_ancestor_of?(categories(c))
507
+ end
508
+ assert !categories(:top_level).is_or_is_ancestor_of?(categories(:top_level_2))
509
+ end
510
+
511
+ def test_left_and_rights_valid_with_blank_left
512
+ assert Category.left_and_rights_valid?
513
+ categories(:child_2)[:lft] = nil
514
+ categories(:child_2).save(false)
515
+ assert !Category.left_and_rights_valid?
516
+ end
517
+
518
+ def test_left_and_rights_valid_with_blank_right
519
+ assert Category.left_and_rights_valid?
520
+ categories(:child_2)[:rgt] = nil
521
+ categories(:child_2).save(false)
522
+ assert !Category.left_and_rights_valid?
523
+ end
524
+
525
+ def test_left_and_rights_valid_with_equal
526
+ assert Category.left_and_rights_valid?
527
+ categories(:top_level_2)[:lft] = categories(:top_level_2)[:rgt]
528
+ categories(:top_level_2).save(false)
529
+ assert !Category.left_and_rights_valid?
530
+ end
531
+
532
+ def test_left_and_rights_valid_with_left_equal_to_parent
533
+ assert Category.left_and_rights_valid?
534
+ categories(:child_2)[:lft] = categories(:top_level)[:lft]
535
+ categories(:child_2).save(false)
536
+ assert !Category.left_and_rights_valid?
537
+ end
538
+
539
+ def test_left_and_rights_valid_with_right_equal_to_parent
540
+ assert Category.left_and_rights_valid?
541
+ categories(:child_2)[:rgt] = categories(:top_level)[:rgt]
542
+ categories(:child_2).save(false)
543
+ assert !Category.left_and_rights_valid?
544
+ end
545
+
546
+ def test_moving_dirty_objects_doesnt_invalidate_tree
547
+ r1 = Category.create
548
+ r2 = Category.create
549
+ r3 = Category.create
550
+ r4 = Category.create
551
+ nodes = [r1, r2, r3, r4]
552
+
553
+ r2.move_to_child_of(r1)
554
+ assert Category.valid?
555
+
556
+ r3.move_to_child_of(r1)
557
+ assert Category.valid?
558
+
559
+ r4.move_to_child_of(r2)
560
+ assert Category.valid?
561
+ end
562
+
563
+ def test_multi_scoped_no_duplicates_for_columns?
564
+ assert_nothing_raised do
565
+ Note.no_duplicates_for_columns?
566
+ end
567
+ end
568
+
569
+ def test_multi_scoped_all_roots_valid?
570
+ assert_nothing_raised do
571
+ Note.all_roots_valid?
572
+ end
573
+ end
574
+
575
+ def test_multi_scoped
576
+ note1 = Note.create!(:body => "A", :notable_id => 2, :notable_type => 'Category')
577
+ note2 = Note.create!(:body => "B", :notable_id => 2, :notable_type => 'Category')
578
+ note3 = Note.create!(:body => "C", :notable_id => 2, :notable_type => 'Default')
579
+
580
+ assert_equal [note1, note2], note1.self_and_siblings
581
+ assert_equal [note3], note3.self_and_siblings
582
+ end
583
+
584
+ def test_multi_scoped_rebuild
585
+ root = Note.create!(:body => "A", :notable_id => 3, :notable_type => 'Category')
586
+ child1 = Note.create!(:body => "B", :notable_id => 3, :notable_type => 'Category')
587
+ child2 = Note.create!(:body => "C", :notable_id => 3, :notable_type => 'Category')
588
+
589
+ child1.move_to_child_of root
590
+ child2.move_to_child_of root
591
+
592
+ Note.update_all('lft = null, rgt = null')
593
+ Note.rebuild!
594
+
595
+ assert_equal Note.roots.find_by_body('A'), root
596
+ assert_equal [child1, child2], Note.roots.find_by_body('A').children
597
+ end
598
+
599
+ def test_same_scope_with_multi_scopes
600
+ assert_nothing_raised do
601
+ notes(:scope1).same_scope?(notes(:child_1))
602
+ end
603
+ assert notes(:scope1).same_scope?(notes(:child_1))
604
+ assert notes(:child_1).same_scope?(notes(:scope1))
605
+ assert !notes(:scope1).same_scope?(notes(:scope2))
606
+ end
607
+
608
+ def test_quoting_of_multi_scope_column_names
609
+ assert_equal ["\"notable_id\"", "\"notable_type\""], Note.quoted_scope_column_names
610
+ end
611
+
612
+ def test_equal_in_same_scope
613
+ assert_equal notes(:scope1), notes(:scope1)
614
+ assert_not_equal notes(:scope1), notes(:child_1)
615
+ end
616
+
617
+ def test_equal_in_different_scopes
618
+ assert_not_equal notes(:scope1), notes(:scope2)
619
+ end
620
+
621
+ def test_delete_does_not_invalidate
622
+ Category.acts_as_nested_set_options[:dependent] = :delete
623
+ categories(:child_2).destroy
624
+ assert Category.valid?
625
+ end
626
+
627
+ def test_destroy_does_not_invalidate
628
+ Category.acts_as_nested_set_options[:dependent] = :destroy
629
+ categories(:child_2).destroy
630
+ assert Category.valid?
631
+ end
632
+
633
+ def test_destroy_multiple_times_does_not_invalidate
634
+ Category.acts_as_nested_set_options[:dependent] = :destroy
635
+ categories(:child_2).destroy
636
+ categories(:child_2).destroy
637
+ assert Category.valid?
638
+ end
639
+
640
+ def test_assigning_parent_id_on_create
641
+ category = Category.create!(:name => "Child", :parent_id => categories(:child_2).id)
642
+ assert_equal categories(:child_2), category.parent
643
+ assert_equal categories(:child_2).id, category.parent_id
644
+ assert_not_nil category.left
645
+ assert_not_nil category.right
646
+ assert Category.valid?
647
+ end
648
+
649
+ def test_assigning_parent_on_create
650
+ category = Category.create!(:name => "Child", :parent => categories(:child_2))
651
+ assert_equal categories(:child_2), category.parent
652
+ assert_equal categories(:child_2).id, category.parent_id
653
+ assert_not_nil category.left
654
+ assert_not_nil category.right
655
+ assert Category.valid?
656
+ end
657
+
658
+ def test_assigning_parent_id_to_nil_on_create
659
+ category = Category.create!(:name => "New Root", :parent_id => nil)
660
+ assert_nil category.parent
661
+ assert_nil category.parent_id
662
+ assert_not_nil category.left
663
+ assert_not_nil category.right
664
+ assert Category.valid?
665
+ end
666
+
667
+ def test_assigning_parent_id_on_update
668
+ category = categories(:child_2_1)
669
+ category.parent_id = categories(:child_3).id
670
+ category.save
671
+ assert_equal categories(:child_3), category.parent
672
+ assert_equal categories(:child_3).id, category.parent_id
673
+ assert Category.valid?
674
+ end
675
+
676
+ def test_assigning_parent_on_update
677
+ category = categories(:child_2_1)
678
+ category.parent = categories(:child_3)
679
+ category.save
680
+ assert_equal categories(:child_3), category.parent
681
+ assert_equal categories(:child_3).id, category.parent_id
682
+ assert Category.valid?
683
+ end
684
+
685
+ def test_assigning_parent_id_to_nil_on_update
686
+ category = categories(:child_2_1)
687
+ category.parent_id = nil
688
+ category.save
689
+ assert_nil category.parent
690
+ assert_nil category.parent_id
691
+ assert Category.valid?
692
+ end
693
+
694
+ def test_creating_child_from_parent
695
+ category = categories(:child_2).children.create!(:name => "Child")
696
+ assert_equal categories(:child_2), category.parent
697
+ assert_equal categories(:child_2).id, category.parent_id
698
+ assert_not_nil category.left
699
+ assert_not_nil category.right
700
+ assert Category.valid?
701
+ end
702
+
703
+ def check_structure(entries, structure)
704
+ structure = structure.dup
705
+ Category.each_with_level(entries) do |category, level|
706
+ expected_level, expected_name = structure.shift
707
+ assert_equal expected_name, category.name, "wrong category"
708
+ assert_equal expected_level, level, "wrong level for #{category.name}"
709
+ end
710
+ end
711
+
712
+ def test_each_with_level
713
+ levels = [
714
+ [0, "Top Level"],
715
+ [1, "Child 1"],
716
+ [1, "Child 2"],
717
+ [2, "Child 2.1"],
718
+ [1, "Child 3" ]]
719
+
720
+ check_structure(Category.root.self_and_descendants, levels)
721
+
722
+ # test some deeper structures
723
+ category = Category.find_by_name("Child 1")
724
+ c1 = Category.new(:name => "Child 1.1")
725
+ c2 = Category.new(:name => "Child 1.1.1")
726
+ c3 = Category.new(:name => "Child 1.1.1.1")
727
+ c4 = Category.new(:name => "Child 1.2")
728
+ [c1, c2, c3, c4].each(&:save!)
729
+
730
+ c1.move_to_child_of(category)
731
+ c2.move_to_child_of(c1)
732
+ c3.move_to_child_of(c2)
733
+ c4.move_to_child_of(category)
734
+
735
+ levels = [
736
+ [0, "Top Level"],
737
+ [1, "Child 1"],
738
+ [2, "Child 1.1"],
739
+ [3, "Child 1.1.1"],
740
+ [4, "Child 1.1.1.1"],
741
+ [2, "Child 1.2"],
742
+ [1, "Child 2"],
743
+ [2, "Child 2.1"],
744
+ [1, "Child 3" ]]
745
+
746
+ check_structure(Category.root.self_and_descendants, levels)
747
+ end
748
+
749
+ def test_model_with_attr_accessible
750
+ model = Class.new(ActiveRecord::Base)
751
+ model.set_table_name 'categories'
752
+ model.attr_accessible :name
753
+ assert_nothing_raised do
754
+ model.acts_as_nested_set
755
+ model.new(:name => 'foo')
756
+ end
757
+ end
758
+
759
+ def test_before_move_callback
760
+ @called = false
761
+ Category.before_move do |record|
762
+ @called = true
763
+ end
764
+ categories(:child_2).move_to_root
765
+ assert @called
766
+ ensure
767
+ Category.before_move_callback_chain.pop
768
+ end
769
+
770
+ def test_before_move_callback_returning_false_stops_move
771
+ Category.before_move do
772
+ return false
773
+ end
774
+ assert !categories(:child_3).move_to_root
775
+ assert !categories(:child_3).root?
776
+ ensure
777
+ Category.before_move_callback_chain.pop
778
+ end
779
+
780
+ def test_before_move_callback_returning_false_halts_save
781
+ Category.before_move do
782
+ return false
783
+ end
784
+ categories(:child_3).parent_id = nil
785
+ assert !categories(:child_3).save
786
+ ensure
787
+ Category.before_move_callback_chain.pop
788
+ end
789
+
790
+ def test_calls_after_save_when_moving
791
+ @called = false
792
+ Category.after_save do
793
+ @called = true
794
+ end
795
+ categories(:child_3).parent = categories(:child_2)
796
+ assert categories(:child_3).save
797
+ assert @called
798
+ ensure
799
+ Category.after_save_callback_chain.pop
800
+ end
801
+ end