comparison .svn/pristine/ee/ee3e0d946d377acd7e76d501db77540601a10ca7.svn-base @ 1295:622f24f53b42 redmine-2.3

Update to Redmine SVN revision 11972 on 2.3-stable branch
author Chris Cannam
date Fri, 14 Jun 2013 09:02:21 +0100
parents
children
comparison
equal deleted inserted replaced
1294:3e4c3460b6ca 1295:622f24f53b42
1 require 'spec_helper'
2
3 describe "AwesomeNestedSet" do
4 before(:all) do
5 self.class.fixtures :categories, :departments, :notes, :things, :brokens
6 end
7
8 describe "defaults" do
9 it "should have left_column_default" do
10 Default.acts_as_nested_set_options[:left_column].should == 'lft'
11 end
12
13 it "should have right_column_default" do
14 Default.acts_as_nested_set_options[:right_column].should == 'rgt'
15 end
16
17 it "should have parent_column_default" do
18 Default.acts_as_nested_set_options[:parent_column].should == 'parent_id'
19 end
20
21 it "should have scope_default" do
22 Default.acts_as_nested_set_options[:scope].should be_nil
23 end
24
25 it "should have left_column_name" do
26 Default.left_column_name.should == 'lft'
27 Default.new.left_column_name.should == 'lft'
28 RenamedColumns.left_column_name.should == 'red'
29 RenamedColumns.new.left_column_name.should == 'red'
30 end
31
32 it "should have right_column_name" do
33 Default.right_column_name.should == 'rgt'
34 Default.new.right_column_name.should == 'rgt'
35 RenamedColumns.right_column_name.should == 'black'
36 RenamedColumns.new.right_column_name.should == 'black'
37 end
38
39 it "should have parent_column_name" do
40 Default.parent_column_name.should == 'parent_id'
41 Default.new.parent_column_name.should == 'parent_id'
42 RenamedColumns.parent_column_name.should == 'mother_id'
43 RenamedColumns.new.parent_column_name.should == 'mother_id'
44 end
45 end
46
47 it "creation_with_altered_column_names" do
48 lambda {
49 RenamedColumns.create!()
50 }.should_not raise_exception
51 end
52
53 it "creation when existing record has nil left column" do
54 assert_nothing_raised do
55 Broken.create!
56 end
57 end
58
59 it "quoted_left_column_name" do
60 quoted = Default.connection.quote_column_name('lft')
61 Default.quoted_left_column_name.should == quoted
62 Default.new.quoted_left_column_name.should == quoted
63 end
64
65 it "quoted_right_column_name" do
66 quoted = Default.connection.quote_column_name('rgt')
67 Default.quoted_right_column_name.should == quoted
68 Default.new.quoted_right_column_name.should == quoted
69 end
70
71 it "left_column_protected_from_assignment" do
72 lambda {
73 Category.new.lft = 1
74 }.should raise_exception(ActiveRecord::ActiveRecordError)
75 end
76
77 it "right_column_protected_from_assignment" do
78 lambda {
79 Category.new.rgt = 1
80 }.should raise_exception(ActiveRecord::ActiveRecordError)
81 end
82
83 it "scoped_appends_id" do
84 ScopedCategory.acts_as_nested_set_options[:scope].should == :organization_id
85 end
86
87 it "roots_class_method" do
88 Category.roots.should == Category.find_all_by_parent_id(nil)
89 end
90
91 it "root_class_method" do
92 Category.root.should == categories(:top_level)
93 end
94
95 it "root" do
96 categories(:child_3).root.should == categories(:top_level)
97 end
98
99 it "root?" do
100 categories(:top_level).root?.should be_true
101 categories(:top_level_2).root?.should be_true
102 end
103
104 it "leaves_class_method" do
105 Category.find(:all, :conditions => "#{Category.right_column_name} - #{Category.left_column_name} = 1").should == Category.leaves
106 Category.leaves.count.should == 4
107 Category.leaves.should include(categories(:child_1))
108 Category.leaves.should include(categories(:child_2_1))
109 Category.leaves.should include(categories(:child_3))
110 Category.leaves.should include(categories(:top_level_2))
111 end
112
113 it "leaf" do
114 categories(:child_1).leaf?.should be_true
115 categories(:child_2_1).leaf?.should be_true
116 categories(:child_3).leaf?.should be_true
117 categories(:top_level_2).leaf?.should be_true
118
119 categories(:top_level).leaf?.should be_false
120 categories(:child_2).leaf?.should be_false
121 Category.new.leaf?.should be_false
122 end
123
124
125 it "parent" do
126 categories(:child_2_1).parent.should == categories(:child_2)
127 end
128
129 it "self_and_ancestors" do
130 child = categories(:child_2_1)
131 self_and_ancestors = [categories(:top_level), categories(:child_2), child]
132 self_and_ancestors.should == child.self_and_ancestors
133 end
134
135 it "ancestors" do
136 child = categories(:child_2_1)
137 ancestors = [categories(:top_level), categories(:child_2)]
138 ancestors.should == child.ancestors
139 end
140
141 it "self_and_siblings" do
142 child = categories(:child_2)
143 self_and_siblings = [categories(:child_1), child, categories(:child_3)]
144 self_and_siblings.should == child.self_and_siblings
145 lambda do
146 tops = [categories(:top_level), categories(:top_level_2)]
147 assert_equal tops, categories(:top_level).self_and_siblings
148 end.should_not raise_exception
149 end
150
151 it "siblings" do
152 child = categories(:child_2)
153 siblings = [categories(:child_1), categories(:child_3)]
154 siblings.should == child.siblings
155 end
156
157 it "leaves" do
158 leaves = [categories(:child_1), categories(:child_2_1), categories(:child_3)]
159 categories(:top_level).leaves.should == leaves
160 end
161
162 it "level" do
163 categories(:top_level).level.should == 0
164 categories(:child_1).level.should == 1
165 categories(:child_2_1).level.should == 2
166 end
167
168 it "has_children?" do
169 categories(:child_2_1).children.empty?.should be_true
170 categories(:child_2).children.empty?.should be_false
171 categories(:top_level).children.empty?.should be_false
172 end
173
174 it "self_and_descendents" do
175 parent = categories(:top_level)
176 self_and_descendants = [parent, categories(:child_1), categories(:child_2),
177 categories(:child_2_1), categories(:child_3)]
178 self_and_descendants.should == parent.self_and_descendants
179 self_and_descendants.count.should == parent.self_and_descendants.count
180 end
181
182 it "descendents" do
183 lawyers = Category.create!(:name => "lawyers")
184 us = Category.create!(:name => "United States")
185 us.move_to_child_of(lawyers)
186 patent = Category.create!(:name => "Patent Law")
187 patent.move_to_child_of(us)
188 lawyers.reload
189
190 lawyers.children.size.should == 1
191 us.children.size.should == 1
192 lawyers.descendants.size.should == 2
193 end
194
195 it "self_and_descendents" do
196 parent = categories(:top_level)
197 descendants = [categories(:child_1), categories(:child_2),
198 categories(:child_2_1), categories(:child_3)]
199 descendants.should == parent.descendants
200 end
201
202 it "children" do
203 category = categories(:top_level)
204 category.children.each {|c| category.id.should == c.parent_id }
205 end
206
207 it "order_of_children" do
208 categories(:child_2).move_left
209 categories(:child_2).should == categories(:top_level).children[0]
210 categories(:child_1).should == categories(:top_level).children[1]
211 categories(:child_3).should == categories(:top_level).children[2]
212 end
213
214 it "is_or_is_ancestor_of?" do
215 categories(:top_level).is_or_is_ancestor_of?(categories(:child_1)).should be_true
216 categories(:top_level).is_or_is_ancestor_of?(categories(:child_2_1)).should be_true
217 categories(:child_2).is_or_is_ancestor_of?(categories(:child_2_1)).should be_true
218 categories(:child_2_1).is_or_is_ancestor_of?(categories(:child_2)).should be_false
219 categories(:child_1).is_or_is_ancestor_of?(categories(:child_2)).should be_false
220 categories(:child_1).is_or_is_ancestor_of?(categories(:child_1)).should be_true
221 end
222
223 it "is_ancestor_of?" do
224 categories(:top_level).is_ancestor_of?(categories(:child_1)).should be_true
225 categories(:top_level).is_ancestor_of?(categories(:child_2_1)).should be_true
226 categories(:child_2).is_ancestor_of?(categories(:child_2_1)).should be_true
227 categories(:child_2_1).is_ancestor_of?(categories(:child_2)).should be_false
228 categories(:child_1).is_ancestor_of?(categories(:child_2)).should be_false
229 categories(:child_1).is_ancestor_of?(categories(:child_1)).should be_false
230 end
231
232 it "is_or_is_ancestor_of_with_scope" do
233 root = ScopedCategory.root
234 child = root.children.first
235 root.is_or_is_ancestor_of?(child).should be_true
236 child.update_attribute :organization_id, 'different'
237 root.is_or_is_ancestor_of?(child).should be_false
238 end
239
240 it "is_or_is_descendant_of?" do
241 categories(:child_1).is_or_is_descendant_of?(categories(:top_level)).should be_true
242 categories(:child_2_1).is_or_is_descendant_of?(categories(:top_level)).should be_true
243 categories(:child_2_1).is_or_is_descendant_of?(categories(:child_2)).should be_true
244 categories(:child_2).is_or_is_descendant_of?(categories(:child_2_1)).should be_false
245 categories(:child_2).is_or_is_descendant_of?(categories(:child_1)).should be_false
246 categories(:child_1).is_or_is_descendant_of?(categories(:child_1)).should be_true
247 end
248
249 it "is_descendant_of?" do
250 categories(:child_1).is_descendant_of?(categories(:top_level)).should be_true
251 categories(:child_2_1).is_descendant_of?(categories(:top_level)).should be_true
252 categories(:child_2_1).is_descendant_of?(categories(:child_2)).should be_true
253 categories(:child_2).is_descendant_of?(categories(:child_2_1)).should be_false
254 categories(:child_2).is_descendant_of?(categories(:child_1)).should be_false
255 categories(:child_1).is_descendant_of?(categories(:child_1)).should be_false
256 end
257
258 it "is_or_is_descendant_of_with_scope" do
259 root = ScopedCategory.root
260 child = root.children.first
261 child.is_or_is_descendant_of?(root).should be_true
262 child.update_attribute :organization_id, 'different'
263 child.is_or_is_descendant_of?(root).should be_false
264 end
265
266 it "same_scope?" do
267 root = ScopedCategory.root
268 child = root.children.first
269 child.same_scope?(root).should be_true
270 child.update_attribute :organization_id, 'different'
271 child.same_scope?(root).should be_false
272 end
273
274 it "left_sibling" do
275 categories(:child_1).should == categories(:child_2).left_sibling
276 categories(:child_2).should == categories(:child_3).left_sibling
277 end
278
279 it "left_sibling_of_root" do
280 categories(:top_level).left_sibling.should be_nil
281 end
282
283 it "left_sibling_without_siblings" do
284 categories(:child_2_1).left_sibling.should be_nil
285 end
286
287 it "left_sibling_of_leftmost_node" do
288 categories(:child_1).left_sibling.should be_nil
289 end
290
291 it "right_sibling" do
292 categories(:child_3).should == categories(:child_2).right_sibling
293 categories(:child_2).should == categories(:child_1).right_sibling
294 end
295
296 it "right_sibling_of_root" do
297 categories(:top_level_2).should == categories(:top_level).right_sibling
298 categories(:top_level_2).right_sibling.should be_nil
299 end
300
301 it "right_sibling_without_siblings" do
302 categories(:child_2_1).right_sibling.should be_nil
303 end
304
305 it "right_sibling_of_rightmost_node" do
306 categories(:child_3).right_sibling.should be_nil
307 end
308
309 it "move_left" do
310 categories(:child_2).move_left
311 categories(:child_2).left_sibling.should be_nil
312 categories(:child_1).should == categories(:child_2).right_sibling
313 Category.valid?.should be_true
314 end
315
316 it "move_right" do
317 categories(:child_2).move_right
318 categories(:child_2).right_sibling.should be_nil
319 categories(:child_3).should == categories(:child_2).left_sibling
320 Category.valid?.should be_true
321 end
322
323 it "move_to_left_of" do
324 categories(:child_3).move_to_left_of(categories(:child_1))
325 categories(:child_3).left_sibling.should be_nil
326 categories(:child_1).should == categories(:child_3).right_sibling
327 Category.valid?.should be_true
328 end
329
330 it "move_to_right_of" do
331 categories(:child_1).move_to_right_of(categories(:child_3))
332 categories(:child_1).right_sibling.should be_nil
333 categories(:child_3).should == categories(:child_1).left_sibling
334 Category.valid?.should be_true
335 end
336
337 it "move_to_root" do
338 categories(:child_2).move_to_root
339 categories(:child_2).parent.should be_nil
340 categories(:child_2).level.should == 0
341 categories(:child_2_1).level.should == 1
342 categories(:child_2).left.should == 1
343 categories(:child_2).right.should == 4
344 Category.valid?.should be_true
345 end
346
347 it "move_to_child_of" do
348 categories(:child_1).move_to_child_of(categories(:child_3))
349 categories(:child_3).id.should == categories(:child_1).parent_id
350 Category.valid?.should be_true
351 end
352
353 it "move_to_child_of_appends_to_end" do
354 child = Category.create! :name => 'New Child'
355 child.move_to_child_of categories(:top_level)
356 child.should == categories(:top_level).children.last
357 end
358
359 it "subtree_move_to_child_of" do
360 categories(:child_2).left.should == 4
361 categories(:child_2).right.should == 7
362
363 categories(:child_1).left.should == 2
364 categories(:child_1).right.should == 3
365
366 categories(:child_2).move_to_child_of(categories(:child_1))
367 Category.valid?.should be_true
368 categories(:child_1).id.should == categories(:child_2).parent_id
369
370 categories(:child_2).left.should == 3
371 categories(:child_2).right.should == 6
372 categories(:child_1).left.should == 2
373 categories(:child_1).right.should == 7
374 end
375
376 it "slightly_difficult_move_to_child_of" do
377 categories(:top_level_2).left.should == 11
378 categories(:top_level_2).right.should == 12
379
380 # create a new top-level node and move single-node top-level tree inside it.
381 new_top = Category.create(:name => 'New Top')
382 new_top.left.should == 13
383 new_top.right.should == 14
384
385 categories(:top_level_2).move_to_child_of(new_top)
386
387 Category.valid?.should be_true
388 new_top.id.should == categories(:top_level_2).parent_id
389
390 categories(:top_level_2).left.should == 12
391 categories(:top_level_2).right.should == 13
392 new_top.left.should == 11
393 new_top.right.should == 14
394 end
395
396 it "difficult_move_to_child_of" do
397 categories(:top_level).left.should == 1
398 categories(:top_level).right.should == 10
399 categories(:child_2_1).left.should == 5
400 categories(:child_2_1).right.should == 6
401
402 # create a new top-level node and move an entire top-level tree inside it.
403 new_top = Category.create(:name => 'New Top')
404 categories(:top_level).move_to_child_of(new_top)
405 categories(:child_2_1).reload
406 Category.valid?.should be_true
407 new_top.id.should == categories(:top_level).parent_id
408
409 categories(:top_level).left.should == 4
410 categories(:top_level).right.should == 13
411 categories(:child_2_1).left.should == 8
412 categories(:child_2_1).right.should == 9
413 end
414
415 #rebuild swaps the position of the 2 children when added using move_to_child twice onto same parent
416 it "move_to_child_more_than_once_per_parent_rebuild" do
417 root1 = Category.create(:name => 'Root1')
418 root2 = Category.create(:name => 'Root2')
419 root3 = Category.create(:name => 'Root3')
420
421 root2.move_to_child_of root1
422 root3.move_to_child_of root1
423
424 output = Category.roots.last.to_text
425 Category.update_all('lft = null, rgt = null')
426 Category.rebuild!
427
428 Category.roots.last.to_text.should == output
429 end
430
431 # doing move_to_child twice onto same parent from the furthest right first
432 it "move_to_child_more_than_once_per_parent_outside_in" do
433 node1 = Category.create(:name => 'Node-1')
434 node2 = Category.create(:name => 'Node-2')
435 node3 = Category.create(:name => 'Node-3')
436
437 node2.move_to_child_of node1
438 node3.move_to_child_of node1
439
440 output = Category.roots.last.to_text
441 Category.update_all('lft = null, rgt = null')
442 Category.rebuild!
443
444 Category.roots.last.to_text.should == output
445 end
446
447 it "should be able to rebuild without validating each record" do
448 root1 = Category.create(:name => 'Root1')
449 root2 = Category.create(:name => 'Root2')
450 root3 = Category.create(:name => 'Root3')
451
452 root2.move_to_child_of root1
453 root3.move_to_child_of root1
454
455 root2.name = nil
456 root2.save!(:validate => false)
457
458 output = Category.roots.last.to_text
459 Category.update_all('lft = null, rgt = null')
460 Category.rebuild!(false)
461
462 Category.roots.last.to_text.should == output
463 end
464
465 it "valid_with_null_lefts" do
466 Category.valid?.should be_true
467 Category.update_all('lft = null')
468 Category.valid?.should be_false
469 end
470
471 it "valid_with_null_rights" do
472 Category.valid?.should be_true
473 Category.update_all('rgt = null')
474 Category.valid?.should be_false
475 end
476
477 it "valid_with_missing_intermediate_node" do
478 # Even though child_2_1 will still exist, it is a sign of a sloppy delete, not an invalid tree.
479 Category.valid?.should be_true
480 Category.delete(categories(:child_2).id)
481 Category.valid?.should be_true
482 end
483
484 it "valid_with_overlapping_and_rights" do
485 Category.valid?.should be_true
486 categories(:top_level_2)['lft'] = 0
487 categories(:top_level_2).save
488 Category.valid?.should be_false
489 end
490
491 it "rebuild" do
492 Category.valid?.should be_true
493 before_text = Category.root.to_text
494 Category.update_all('lft = null, rgt = null')
495 Category.rebuild!
496 Category.valid?.should be_true
497 before_text.should == Category.root.to_text
498 end
499
500 it "move_possible_for_sibling" do
501 categories(:child_2).move_possible?(categories(:child_1)).should be_true
502 end
503
504 it "move_not_possible_to_self" do
505 categories(:top_level).move_possible?(categories(:top_level)).should be_false
506 end
507
508 it "move_not_possible_to_parent" do
509 categories(:top_level).descendants.each do |descendant|
510 categories(:top_level).move_possible?(descendant).should be_false
511 descendant.move_possible?(categories(:top_level)).should be_true
512 end
513 end
514
515 it "is_or_is_ancestor_of?" do
516 [:child_1, :child_2, :child_2_1, :child_3].each do |c|
517 categories(:top_level).is_or_is_ancestor_of?(categories(c)).should be_true
518 end
519 categories(:top_level).is_or_is_ancestor_of?(categories(:top_level_2)).should be_false
520 end
521
522 it "left_and_rights_valid_with_blank_left" do
523 Category.left_and_rights_valid?.should be_true
524 categories(:child_2)[:lft] = nil
525 categories(:child_2).save(:validate => false)
526 Category.left_and_rights_valid?.should be_false
527 end
528
529 it "left_and_rights_valid_with_blank_right" do
530 Category.left_and_rights_valid?.should be_true
531 categories(:child_2)[:rgt] = nil
532 categories(:child_2).save(:validate => false)
533 Category.left_and_rights_valid?.should be_false
534 end
535
536 it "left_and_rights_valid_with_equal" do
537 Category.left_and_rights_valid?.should be_true
538 categories(:top_level_2)[:lft] = categories(:top_level_2)[:rgt]
539 categories(:top_level_2).save(:validate => false)
540 Category.left_and_rights_valid?.should be_false
541 end
542
543 it "left_and_rights_valid_with_left_equal_to_parent" do
544 Category.left_and_rights_valid?.should be_true
545 categories(:child_2)[:lft] = categories(:top_level)[:lft]
546 categories(:child_2).save(:validate => false)
547 Category.left_and_rights_valid?.should be_false
548 end
549
550 it "left_and_rights_valid_with_right_equal_to_parent" do
551 Category.left_and_rights_valid?.should be_true
552 categories(:child_2)[:rgt] = categories(:top_level)[:rgt]
553 categories(:child_2).save(:validate => false)
554 Category.left_and_rights_valid?.should be_false
555 end
556
557 it "moving_dirty_objects_doesnt_invalidate_tree" do
558 r1 = Category.create :name => "Test 1"
559 r2 = Category.create :name => "Test 2"
560 r3 = Category.create :name => "Test 3"
561 r4 = Category.create :name => "Test 4"
562 nodes = [r1, r2, r3, r4]
563
564 r2.move_to_child_of(r1)
565 Category.valid?.should be_true
566
567 r3.move_to_child_of(r1)
568 Category.valid?.should be_true
569
570 r4.move_to_child_of(r2)
571 Category.valid?.should be_true
572 end
573
574 it "multi_scoped_no_duplicates_for_columns?" do
575 lambda {
576 Note.no_duplicates_for_columns?
577 }.should_not raise_exception
578 end
579
580 it "multi_scoped_all_roots_valid?" do
581 lambda {
582 Note.all_roots_valid?
583 }.should_not raise_exception
584 end
585
586 it "multi_scoped" do
587 note1 = Note.create!(:body => "A", :notable_id => 2, :notable_type => 'Category')
588 note2 = Note.create!(:body => "B", :notable_id => 2, :notable_type => 'Category')
589 note3 = Note.create!(:body => "C", :notable_id => 2, :notable_type => 'Default')
590
591 [note1, note2].should == note1.self_and_siblings
592 [note3].should == note3.self_and_siblings
593 end
594
595 it "multi_scoped_rebuild" do
596 root = Note.create!(:body => "A", :notable_id => 3, :notable_type => 'Category')
597 child1 = Note.create!(:body => "B", :notable_id => 3, :notable_type => 'Category')
598 child2 = Note.create!(:body => "C", :notable_id => 3, :notable_type => 'Category')
599
600 child1.move_to_child_of root
601 child2.move_to_child_of root
602
603 Note.update_all('lft = null, rgt = null')
604 Note.rebuild!
605
606 Note.roots.find_by_body('A').should == root
607 [child1, child2].should == Note.roots.find_by_body('A').children
608 end
609
610 it "same_scope_with_multi_scopes" do
611 lambda {
612 notes(:scope1).same_scope?(notes(:child_1))
613 }.should_not raise_exception
614 notes(:scope1).same_scope?(notes(:child_1)).should be_true
615 notes(:child_1).same_scope?(notes(:scope1)).should be_true
616 notes(:scope1).same_scope?(notes(:scope2)).should be_false
617 end
618
619 it "quoting_of_multi_scope_column_names" do
620 ["\"notable_id\"", "\"notable_type\""].should == Note.quoted_scope_column_names
621 end
622
623 it "equal_in_same_scope" do
624 notes(:scope1).should == notes(:scope1)
625 notes(:scope1).should_not == notes(:child_1)
626 end
627
628 it "equal_in_different_scopes" do
629 notes(:scope1).should_not == notes(:scope2)
630 end
631
632 it "delete_does_not_invalidate" do
633 Category.acts_as_nested_set_options[:dependent] = :delete
634 categories(:child_2).destroy
635 Category.valid?.should be_true
636 end
637
638 it "destroy_does_not_invalidate" do
639 Category.acts_as_nested_set_options[:dependent] = :destroy
640 categories(:child_2).destroy
641 Category.valid?.should be_true
642 end
643
644 it "destroy_multiple_times_does_not_invalidate" do
645 Category.acts_as_nested_set_options[:dependent] = :destroy
646 categories(:child_2).destroy
647 categories(:child_2).destroy
648 Category.valid?.should be_true
649 end
650
651 it "assigning_parent_id_on_create" do
652 category = Category.create!(:name => "Child", :parent_id => categories(:child_2).id)
653 categories(:child_2).should == category.parent
654 categories(:child_2).id.should == category.parent_id
655 category.left.should_not be_nil
656 category.right.should_not be_nil
657 Category.valid?.should be_true
658 end
659
660 it "assigning_parent_on_create" do
661 category = Category.create!(:name => "Child", :parent => categories(:child_2))
662 categories(:child_2).should == category.parent
663 categories(:child_2).id.should == category.parent_id
664 category.left.should_not be_nil
665 category.right.should_not be_nil
666 Category.valid?.should be_true
667 end
668
669 it "assigning_parent_id_to_nil_on_create" do
670 category = Category.create!(:name => "New Root", :parent_id => nil)
671 category.parent.should be_nil
672 category.parent_id.should be_nil
673 category.left.should_not be_nil
674 category.right.should_not be_nil
675 Category.valid?.should be_true
676 end
677
678 it "assigning_parent_id_on_update" do
679 category = categories(:child_2_1)
680 category.parent_id = categories(:child_3).id
681 category.save
682 category.reload
683 categories(:child_3).reload
684 categories(:child_3).should == category.parent
685 categories(:child_3).id.should == category.parent_id
686 Category.valid?.should be_true
687 end
688
689 it "assigning_parent_on_update" do
690 category = categories(:child_2_1)
691 category.parent = categories(:child_3)
692 category.save
693 category.reload
694 categories(:child_3).reload
695 categories(:child_3).should == category.parent
696 categories(:child_3).id.should == category.parent_id
697 Category.valid?.should be_true
698 end
699
700 it "assigning_parent_id_to_nil_on_update" do
701 category = categories(:child_2_1)
702 category.parent_id = nil
703 category.save
704 category.parent.should be_nil
705 category.parent_id.should be_nil
706 Category.valid?.should be_true
707 end
708
709 it "creating_child_from_parent" do
710 category = categories(:child_2).children.create!(:name => "Child")
711 categories(:child_2).should == category.parent
712 categories(:child_2).id.should == category.parent_id
713 category.left.should_not be_nil
714 category.right.should_not be_nil
715 Category.valid?.should be_true
716 end
717
718 def check_structure(entries, structure)
719 structure = structure.dup
720 Category.each_with_level(entries) do |category, level|
721 expected_level, expected_name = structure.shift
722 expected_name.should == category.name
723 expected_level.should == level
724 end
725 end
726
727 it "each_with_level" do
728 levels = [
729 [0, "Top Level"],
730 [1, "Child 1"],
731 [1, "Child 2"],
732 [2, "Child 2.1"],
733 [1, "Child 3" ]]
734
735 check_structure(Category.root.self_and_descendants, levels)
736
737 # test some deeper structures
738 category = Category.find_by_name("Child 1")
739 c1 = Category.new(:name => "Child 1.1")
740 c2 = Category.new(:name => "Child 1.1.1")
741 c3 = Category.new(:name => "Child 1.1.1.1")
742 c4 = Category.new(:name => "Child 1.2")
743 [c1, c2, c3, c4].each(&:save!)
744
745 c1.move_to_child_of(category)
746 c2.move_to_child_of(c1)
747 c3.move_to_child_of(c2)
748 c4.move_to_child_of(category)
749
750 levels = [
751 [0, "Top Level"],
752 [1, "Child 1"],
753 [2, "Child 1.1"],
754 [3, "Child 1.1.1"],
755 [4, "Child 1.1.1.1"],
756 [2, "Child 1.2"],
757 [1, "Child 2"],
758 [2, "Child 2.1"],
759 [1, "Child 3" ]]
760
761 check_structure(Category.root.self_and_descendants, levels)
762 end
763
764 it "should not error on a model with attr_accessible" do
765 model = Class.new(ActiveRecord::Base)
766 model.table_name = 'categories'
767 model.attr_accessible :name
768 lambda {
769 model.acts_as_nested_set
770 model.new(:name => 'foo')
771 }.should_not raise_exception
772 end
773
774 describe "before_move_callback" do
775 it "should fire the callback" do
776 categories(:child_2).should_receive(:custom_before_move)
777 categories(:child_2).move_to_root
778 end
779
780 it "should stop move when callback returns false" do
781 Category.test_allows_move = false
782 categories(:child_3).move_to_root.should be_false
783 categories(:child_3).root?.should be_false
784 end
785
786 it "should not halt save actions" do
787 Category.test_allows_move = false
788 categories(:child_3).parent_id = nil
789 categories(:child_3).save.should be_true
790 end
791 end
792
793 describe "counter_cache" do
794
795 it "should allow use of a counter cache for children" do
796 note1 = things(:parent1)
797 note1.children.count.should == 2
798 end
799
800 it "should increment the counter cache on create" do
801 note1 = things(:parent1)
802 note1.children.count.should == 2
803 note1[:children_count].should == 2
804 note1.children.create :body => 'Child 3'
805 note1.children.count.should == 3
806 note1.reload
807 note1[:children_count].should == 3
808 end
809
810 it "should decrement the counter cache on destroy" do
811 note1 = things(:parent1)
812 note1.children.count.should == 2
813 note1[:children_count].should == 2
814 note1.children.last.destroy
815 note1.children.count.should == 1
816 note1.reload
817 note1[:children_count].should == 1
818 end
819 end
820
821 describe "association callbacks on children" do
822 it "should call the appropriate callbacks on the children :has_many association " do
823 root = DefaultWithCallbacks.create
824 root.should_not be_new_record
825
826 child = root.children.build
827
828 root.before_add.should == child
829 root.after_add.should == child
830
831 root.before_remove.should_not == child
832 root.after_remove.should_not == child
833
834 child.save.should be_true
835 root.children.delete(child).should be_true
836
837 root.before_remove.should == child
838 root.after_remove.should == child
839 end
840 end
841 end