acts_as_ordered_tree 1.3.1 → 2.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/lib/acts_as_ordered_tree.rb +22 -100
  3. data/lib/acts_as_ordered_tree/adapters.rb +17 -0
  4. data/lib/acts_as_ordered_tree/adapters/abstract.rb +23 -0
  5. data/lib/acts_as_ordered_tree/adapters/postgresql.rb +150 -0
  6. data/lib/acts_as_ordered_tree/adapters/recursive.rb +157 -0
  7. data/lib/acts_as_ordered_tree/compatibility.rb +22 -0
  8. data/lib/acts_as_ordered_tree/compatibility/active_record/association_scope.rb +9 -0
  9. data/lib/acts_as_ordered_tree/compatibility/active_record/default_scoped.rb +19 -0
  10. data/lib/acts_as_ordered_tree/compatibility/active_record/null_relation.rb +71 -0
  11. data/lib/acts_as_ordered_tree/compatibility/features.rb +153 -0
  12. data/lib/acts_as_ordered_tree/deprecate.rb +24 -0
  13. data/lib/acts_as_ordered_tree/hooks.rb +38 -0
  14. data/lib/acts_as_ordered_tree/hooks/update.rb +86 -0
  15. data/lib/acts_as_ordered_tree/instance_methods.rb +92 -453
  16. data/lib/acts_as_ordered_tree/iterators/arranger.rb +35 -0
  17. data/lib/acts_as_ordered_tree/iterators/level_calculator.rb +52 -0
  18. data/lib/acts_as_ordered_tree/iterators/orphans_pruner.rb +58 -0
  19. data/lib/acts_as_ordered_tree/node.rb +78 -0
  20. data/lib/acts_as_ordered_tree/node/attributes.rb +48 -0
  21. data/lib/acts_as_ordered_tree/node/movement.rb +62 -0
  22. data/lib/acts_as_ordered_tree/node/movements.rb +111 -0
  23. data/lib/acts_as_ordered_tree/node/predicates.rb +98 -0
  24. data/lib/acts_as_ordered_tree/node/reloading.rb +49 -0
  25. data/lib/acts_as_ordered_tree/node/siblings.rb +139 -0
  26. data/lib/acts_as_ordered_tree/node/traversals.rb +53 -0
  27. data/lib/acts_as_ordered_tree/persevering_transaction.rb +93 -0
  28. data/lib/acts_as_ordered_tree/position.rb +143 -0
  29. data/lib/acts_as_ordered_tree/relation/arrangeable.rb +33 -0
  30. data/lib/acts_as_ordered_tree/relation/iterable.rb +41 -0
  31. data/lib/acts_as_ordered_tree/relation/preloaded.rb +46 -11
  32. data/lib/acts_as_ordered_tree/transaction/base.rb +57 -0
  33. data/lib/acts_as_ordered_tree/transaction/callbacks.rb +67 -0
  34. data/lib/acts_as_ordered_tree/transaction/create.rb +68 -0
  35. data/lib/acts_as_ordered_tree/transaction/destroy.rb +34 -0
  36. data/lib/acts_as_ordered_tree/transaction/dsl.rb +214 -0
  37. data/lib/acts_as_ordered_tree/transaction/factory.rb +67 -0
  38. data/lib/acts_as_ordered_tree/transaction/move.rb +70 -0
  39. data/lib/acts_as_ordered_tree/transaction/passthrough.rb +12 -0
  40. data/lib/acts_as_ordered_tree/transaction/reorder.rb +42 -0
  41. data/lib/acts_as_ordered_tree/transaction/save.rb +64 -0
  42. data/lib/acts_as_ordered_tree/transaction/update.rb +78 -0
  43. data/lib/acts_as_ordered_tree/tree.rb +148 -0
  44. data/lib/acts_as_ordered_tree/tree/association.rb +20 -0
  45. data/lib/acts_as_ordered_tree/tree/callbacks.rb +57 -0
  46. data/lib/acts_as_ordered_tree/tree/children_association.rb +120 -0
  47. data/lib/acts_as_ordered_tree/tree/columns.rb +102 -0
  48. data/lib/acts_as_ordered_tree/tree/deprecated_columns_accessors.rb +24 -0
  49. data/lib/acts_as_ordered_tree/tree/parent_association.rb +31 -0
  50. data/lib/acts_as_ordered_tree/tree/perseverance.rb +19 -0
  51. data/lib/acts_as_ordered_tree/tree/scopes.rb +56 -0
  52. data/lib/acts_as_ordered_tree/validators.rb +1 -1
  53. data/lib/acts_as_ordered_tree/version.rb +1 -1
  54. data/spec/acts_as_ordered_tree_spec.rb +80 -909
  55. data/spec/adapters/postgresql_spec.rb +14 -0
  56. data/spec/adapters/recursive_spec.rb +12 -0
  57. data/spec/adapters/shared.rb +272 -0
  58. data/spec/callbacks_spec.rb +177 -0
  59. data/spec/counter_cache_spec.rb +31 -0
  60. data/spec/create_spec.rb +110 -0
  61. data/spec/destroy_spec.rb +57 -0
  62. data/spec/inheritance_spec.rb +176 -0
  63. data/spec/move_spec.rb +94 -0
  64. data/spec/node/movements/concurrent_movements_spec.rb +354 -0
  65. data/spec/node/movements/move_higher_spec.rb +46 -0
  66. data/spec/node/movements/move_lower_spec.rb +46 -0
  67. data/spec/node/movements/move_to_child_of_spec.rb +147 -0
  68. data/spec/node/movements/move_to_child_with_index_spec.rb +124 -0
  69. data/spec/node/movements/move_to_child_with_position_spec.rb +85 -0
  70. data/spec/node/movements/move_to_left_of_spec.rb +120 -0
  71. data/spec/node/movements/move_to_right_of_spec.rb +120 -0
  72. data/spec/node/movements/move_to_root_spec.rb +67 -0
  73. data/spec/node/predicates_spec.rb +211 -0
  74. data/spec/node/reloading_spec.rb +42 -0
  75. data/spec/node/siblings_spec.rb +193 -0
  76. data/spec/node/traversals_spec.rb +71 -0
  77. data/spec/persevering_transaction_spec.rb +98 -0
  78. data/spec/relation/arrangeable_spec.rb +88 -0
  79. data/spec/relation/iterable_spec.rb +104 -0
  80. data/spec/relation/preloaded_spec.rb +57 -0
  81. data/spec/reorder_spec.rb +83 -0
  82. data/spec/spec_helper.rb +30 -38
  83. data/spec/support/db/boot.rb +22 -0
  84. data/spec/{db → support/db}/config.travis.yml +2 -0
  85. data/spec/{db → support/db}/config.yml +1 -0
  86. data/spec/{db → support/db}/schema.rb +9 -0
  87. data/spec/support/factories.rb +2 -2
  88. data/spec/support/matchers.rb +67 -58
  89. data/spec/support/models.rb +6 -14
  90. data/spec/support/tree_factory.rb +315 -0
  91. data/spec/tree/children_association_spec.rb +72 -0
  92. data/spec/tree/columns_spec.rb +65 -0
  93. data/spec/tree/scopes_spec.rb +39 -0
  94. metadata +161 -43
  95. data/lib/acts_as_ordered_tree/adapters/postgresql_adapter.rb +0 -104
  96. data/lib/acts_as_ordered_tree/arrangeable.rb +0 -80
  97. data/lib/acts_as_ordered_tree/class_methods.rb +0 -72
  98. data/lib/acts_as_ordered_tree/relation/base.rb +0 -26
  99. data/lib/acts_as_ordered_tree/tenacious_transaction.rb +0 -30
  100. data/spec/concurrency_support_spec.rb +0 -156
@@ -1,3 +1,3 @@
1
1
  module ActsAsOrderedTree
2
- VERSION = '1.3.1'
2
+ VERSION = '2.0.0.beta3'
3
3
  end
@@ -1,947 +1,125 @@
1
1
  require File.expand_path('../spec_helper', __FILE__)
2
2
 
3
3
  describe ActsAsOrderedTree, :transactional do
4
- describe "defaults" do
5
- subject { Default }
6
-
7
- its(:parent_column) { should eq :parent_id }
8
- its(:position_column) { should eq :position }
9
- its(:depth_column) { should eq :depth }
10
- its(:children_counter_cache_column) { be_nil }
11
-
12
- if ActsAsOrderedTree::PROTECTED_ATTRIBUTES_SUPPORTED
13
- context "instance" do
14
- subject { Default.new }
15
-
16
- it { should_not allow_mass_assignment_of(:position) }
17
- it { should_not allow_mass_assignment_of(:depth) }
18
- end
19
- end
20
- end
21
-
22
- describe "default with counter cache" do
23
- subject { DefaultWithCounterCache }
24
-
25
- its(:children_counter_cache_column) { should eq :categories_count }
26
- end
27
-
28
- describe "renamed columns" do
29
- subject { RenamedColumns }
30
-
31
- its(:parent_column) { should eq :mother_id }
32
- its(:position_column) { should eq :red }
33
- its(:depth_column) { should eq :pitch }
34
-
35
- if ActsAsOrderedTree::PROTECTED_ATTRIBUTES_SUPPORTED
36
- context "instance" do
37
- subject { RenamedColumns.new }
38
-
39
- it { should_not allow_mass_assignment_of(:red) }
40
- it { should_not allow_mass_assignment_of(:pitch) }
41
- end
42
- end
43
- end
44
-
45
- it "creation_with_altered_column_names" do
46
- lambda {
47
- RenamedColumns.create!()
48
- }.should_not raise_exception
49
- end
50
-
51
- describe ".roots" do
52
- # create fixture
53
- before { FactoryGirl.create_list(:default, 3) }
54
-
55
- subject { Default.roots }
56
-
57
- its(:entries) { should eq Default.where(:parent_id => nil).order(:position).to_a }
58
- end
59
-
60
- describe ".leaves" do
61
- # create fixture
62
- let(:root) { create :default_with_counter_cache }
63
- before { create_list :default_with_counter_cache, 2, :parent => root }
64
-
65
- subject { DefaultWithCounterCache }
66
-
67
- it { should respond_to(:leaves) }
68
- its(:leaves) { should have(2).items }
69
- end
70
-
71
- describe ".root" do
72
- # create fixture
73
- let!(:root) { create :default }
74
-
75
- context "given a single root node" do
76
- subject { root }
77
-
78
- its(:position) { should eq 1 }
79
- end
80
-
81
- context "given multiple root nodes" do
82
- before { create_list :default, 3 }
83
-
84
- subject { Default }
85
-
86
- its(:root) { should eq root }
87
- end
88
- end
89
-
90
- describe "#root?, #child?, #leaf?, #branch? and #root" do
91
- shared_examples "tree with predicates" do |factory_name|
92
- # create fixture
93
- let!(:root) { create factory_name }
94
- let!(:child) { create factory_name, :parent => root }
95
- let!(:grandchild) { create factory_name, :parent => child }
96
-
97
- before { root.reload }
98
- before { child.reload }
99
- before { grandchild.reload }
100
-
101
- context "given root node" do
102
- subject { root }
103
-
104
- it { should be_root }
105
- it { should_not be_child }
106
- it { should_not be_leaf }
107
- it { should be_branch }
108
- its(:root) { should eq root }
109
- its(:level) { should eq 0 }
110
- end
111
-
112
- context "given a branch node with children" do
113
- subject { child }
114
-
115
- it { should_not be_root }
116
- it { should be_child }
117
- it { should_not be_leaf }
118
- it { should be_branch }
119
- its(:root) { should eq root }
120
- its(:level) { should eq 1 }
121
- end
122
-
123
- context "given a leaf node" do
124
- subject { grandchild }
125
-
126
- it { should_not be_root }
127
- it { should be_child }
128
- it { should be_leaf }
129
- it { should_not be_branch }
130
- its(:root) { should eq root }
131
- its(:level) { should eq 2 }
132
- end
133
-
134
- context "given a new record" do
135
- subject { build factory_name }
136
-
137
- it { should_not be_leaf }
138
- it { should be_branch }
139
- end
140
- end
141
-
142
- it_behaves_like "tree with predicates", :default
143
- it_behaves_like "tree with predicates", :default_with_counter_cache
4
+ example 'creation_with_altered_column_names' do
5
+ expect{RenamedColumns.create!}.not_to raise_error
144
6
  end
145
7
 
146
- describe "#first?, #last?" do
147
- let!(:root) { create :default }
148
- let!(:child_1) { create :default, :parent => root }
149
- let!(:child_2) { create :default, :parent => root }
150
- let!(:child_3) { create :default, :parent => root }
151
-
152
- context "given a node without siblings" do
153
- subject { root }
154
-
155
- it { should be_first }
156
- it { should be_last }
157
- end
158
-
159
- context "given a node, first in the list" do
160
- subject { child_1 }
161
-
162
- it { should be_first }
163
- it { should_not be_last }
164
- end
165
-
166
- context "given a node, nor first neither last" do
167
- subject { child_2 }
168
-
169
- it { should_not be_first }
170
- it { should_not be_last }
171
- end
172
-
173
- context "given a node, last in the list" do
174
- subject { child_3 }
175
-
176
- it { should_not be_first }
177
- it { should be_last }
178
- end
179
- end
180
-
181
- describe "#level" do
182
- context "given a persistent root node" do
8
+ describe '#level' do
9
+ context 'given a persistent root node' do
183
10
  subject { create :default }
184
11
 
185
- its(:level) { should eq 0 }
12
+ it { expect(subject.level).to eq 0 }
186
13
  end
187
- context "given a new root record" do
14
+
15
+ context 'given a new root record' do
188
16
  subject { build :default }
189
17
 
190
- its(:level) { should eq 0 }
18
+ it { expect(subject.level).to eq 0 }
191
19
  end
192
- context "given a persistent node with parent" do
20
+
21
+ context 'given a persistent node with parent' do
193
22
  let(:root) { create :default }
194
23
  subject { create :default, :parent => root }
195
- its(:level) { should eq 1 }
196
- end
197
- context "given a new node with parent" do
198
- let(:root) { create :default }
199
- subject { build :default, :parent => root }
200
- its(:level) { should eq 1 }
201
- end
202
- end
203
-
204
- describe "#self_and_ancestors" do
205
- # create fixture
206
- let!(:root) { create :default }
207
- let!(:child) { create :default, :parent => root }
208
- let!(:grandchild) { create :default, :parent => child }
209
-
210
- context "leaf" do
211
- subject { grandchild.self_and_ancestors }
212
-
213
- it { should be_a ActiveRecord::Relation }
214
- it { should have(3).items }
215
- its(:first) { should eq root }
216
- its(:last) { should eq grandchild }
217
- end
218
-
219
- context "child" do
220
- subject { child.self_and_ancestors }
221
24
 
222
- it { should be_a ActiveRecord::Relation }
223
- it { should have(2).items }
224
- its(:first) { should eq root }
225
- its(:last) { should eq child }
25
+ it { expect(subject.level).to eq 1 }
226
26
  end
227
27
 
228
- context "root" do
229
- subject { root.self_and_ancestors }
230
-
231
- it { should be_a ActiveRecord::Relation }
232
- it { should have(1).item }
233
- its(:first) { should eq root }
234
- end
235
-
236
- context "when record is new" do
237
- let(:record) { build(:default, :parent => grandchild) }
238
- subject { record.self_and_ancestors }
239
-
240
- it { should have(4).items }
241
- it { should include root }
242
- it { should include child }
243
- it { should include grandchild }
244
- it { should include record }
245
- end
246
-
247
- context "when parent is changed" do
248
- before { grandchild.parent = root }
249
- subject { grandchild.self_and_ancestors }
250
-
251
- it { should include root }
252
- it { should_not include child }
253
- it { should include grandchild }
254
- end
255
- end
256
-
257
- describe "#ancestors" do
258
- # create fixture
259
- let!(:root) { create :default }
260
- let!(:child) { create :default, :parent => root }
261
- let!(:grandchild) { create :default, :parent => child }
262
-
263
- context "leaf" do
264
- subject { grandchild.ancestors }
265
-
266
- it { should be_a ActiveRecord::Relation }
267
- it { should have(2).items }
268
- its(:first) { should eq root }
269
- its(:last) { should eq child }
270
- end
271
-
272
- context "child" do
273
- subject { child.ancestors }
274
-
275
- it { should be_a ActiveRecord::Relation }
276
- it { should have(1).item }
277
- its(:first) { should eq root }
278
- end
279
-
280
- context "root" do
281
- subject { root.ancestors }
282
-
283
- it { should be_a ActiveRecord::Relation }
284
- it { should be_empty }
285
- end
286
- end
287
-
288
- describe "#self_and_descendants" do
289
- # create fixture
290
- let!(:root) { create :default }
291
- let!(:child) { create :default, :parent => root }
292
- let!(:grandchild) { create :default, :parent => child }
293
-
294
- context "leaf" do
295
- subject { grandchild.self_and_descendants }
296
-
297
- it { should be_a ActiveRecord::Relation }
298
- it { should have(1).item }
299
- its(:first) { should eq grandchild }
300
- end
301
-
302
- context "child" do
303
- subject { child.self_and_descendants }
304
-
305
- it { should be_a ActiveRecord::Relation }
306
- it { should have(2).items }
307
- its(:first) { should eq child }
308
- its(:last) { should eq grandchild }
309
- end
310
-
311
- context "root" do
312
- subject { root.self_and_descendants }
313
-
314
- it { should be_a ActiveRecord::Relation }
315
- it { should have(3).items }
316
- its(:first) { should eq root }
317
- its(:last) { should eq grandchild }
318
- end
319
- end
320
-
321
- describe "#is_descendant_of?, #is_or_is_descendant_of?, #is_ancestor_of?, #is_or_is_ancestor_of?" do
322
- # create fixture
323
- let!(:root) { create :default }
324
- let!(:child) { create :default, :parent => root }
325
- let!(:grandchild) { create :default, :parent => child }
326
-
327
- context "grandchild" do
328
- subject { grandchild }
329
-
330
- it { should be_is_descendant_of(root) }
331
- it { should be_is_or_is_descendant_of(root) }
332
- it { should_not be_is_ancestor_of(root) }
333
- it { should_not be_is_or_is_ancestor_of(root) }
334
-
335
- it { should be_is_descendant_of(child) }
336
- it { should be_is_or_is_descendant_of(child) }
337
- it { should_not be_is_ancestor_of(child) }
338
- it { should_not be_is_or_is_ancestor_of(child) }
339
-
340
- it { should_not be_is_descendant_of(grandchild) }
341
- it { should be_is_or_is_descendant_of(grandchild) }
342
- it { should_not be_is_ancestor_of(grandchild) }
343
- it { should be_is_or_is_ancestor_of(grandchild) }
344
- end
345
-
346
- context "child" do
347
- subject { child }
348
-
349
- it { should be_is_descendant_of(root) }
350
- it { should be_is_or_is_descendant_of(root) }
351
- it { should_not be_is_ancestor_of(root) }
352
- it { should_not be_is_or_is_ancestor_of(root) }
353
-
354
- it { should_not be_is_descendant_of(child) }
355
- it { should be_is_or_is_descendant_of(child) }
356
- it { should_not be_is_ancestor_of(child) }
357
- it { should be_is_or_is_ancestor_of(child) }
358
-
359
- it { should_not be_is_descendant_of(grandchild) }
360
- it { should_not be_is_or_is_descendant_of(grandchild) }
361
- it { should be_is_ancestor_of(grandchild) }
362
- it { should be_is_or_is_ancestor_of(grandchild) }
363
- end
364
-
365
- context "root" do
366
- subject { root }
367
-
368
- it { should_not be_is_descendant_of(root) }
369
- it { should be_is_or_is_descendant_of(root) }
370
- it { should_not be_is_ancestor_of(root) }
371
- it { should be_is_or_is_ancestor_of(root) }
372
-
373
- it { should_not be_is_descendant_of(child) }
374
- it { should_not be_is_or_is_descendant_of(child) }
375
- it { should be_is_ancestor_of(child) }
376
- it { should be_is_or_is_ancestor_of(child) }
377
-
378
- it { should_not be_is_descendant_of(grandchild) }
379
- it { should_not be_is_or_is_descendant_of(grandchild) }
380
- it { should be_is_ancestor_of(grandchild) }
381
- it { should be_is_or_is_ancestor_of(grandchild) }
382
- end
383
- end
384
-
385
- describe "#left_sibling" do
386
- shared_examples "tree with siblings" do
387
- subject { items }
388
-
389
- its('first.left_sibling') { should be_nil }
390
- its('first.right_sibling') { should eq items.second }
391
-
392
- its('second.left_sibling') { should eq items.first }
393
- its('second.right_sibling') { should eq items.last }
394
-
395
- its('third.left_sibling') { should eq items.second }
396
- its('third.right_sibling') { should be_nil }
397
- end
398
-
399
- context "given unscoped tree" do
400
- it_should_behave_like "tree with siblings" do
401
- let(:items) { create_list :default, 3 }
402
- end
403
- end
404
-
405
- context "given scoped tree" do
406
- let!(:items_1) { create_list :scoped, 3, :scope_type => "s1" }
407
- let!(:items_2) { create_list :scoped, 3, :scope_type => "s2" }
28
+ context 'given a new node with parent' do
29
+ let(:root) { create :default }
30
+ subject { build :default, :parent => root }
408
31
 
409
- it_should_behave_like "tree with siblings" do
410
- let(:items) { items_1 }
411
- end
412
- it_should_behave_like "tree with siblings" do
413
- let(:items) { items_2 }
414
- end
32
+ it { expect(subject.level).to eq 1 }
415
33
  end
416
- end
417
-
418
- describe '#arrange' do
419
- shared_examples 'arrangeable' do
420
- let(:child_1) { root.children.first }
421
- let(:child_2) { root.children.last }
422
- let(:grandchild_11) { child_1.children.first }
423
- let(:grandchild_12) { child_1.children.last }
424
- let(:grandchild_21) { child_2.children.first }
425
- let(:grandchild_22) { child_2.children.last }
426
-
427
- specify '#descendants scope should be arrangeable' do
428
- expect(root.descendants.arrange).to eq Hash[
429
- child_1 => {
430
- grandchild_11 => {},
431
- grandchild_12 => {}
432
- },
433
- child_2 => {
434
- grandchild_21 => {},
435
- grandchild_22 => {}
436
- }
437
- ]
438
- end
439
34
 
440
- specify '#self_and_descendants should be arrangeable' do
441
- expect(root.self_and_descendants.arrange).to eq Hash[
442
- root => {
443
- child_1 => {
444
- grandchild_11 => {},
445
- grandchild_12 => {}
446
- },
447
- child_2 => {
448
- grandchild_21 => {},
449
- grandchild_22 => {}
450
- }
35
+ context 'a model without depth column' do
36
+ tree :factory => :scoped do
37
+ root {
38
+ child {
39
+ grandchild
451
40
  }
452
- ]
41
+ }
453
42
  end
454
43
 
455
- specify '#ancestors should be arrangeable' do
456
- expect(grandchild_11.ancestors.arrange).to eq Hash[
457
- root => {
458
- child_1 => {}
459
- }
460
- ]
461
- end
462
-
463
- specify '#self_and_ancestors should be arrangeable' do
464
- expect(grandchild_11.self_and_ancestors.arrange).to eq Hash[
465
- root => {
466
- child_1 => {
467
- grandchild_11 => {}
468
- }
469
- }
470
- ]
471
- end
44
+ before { root.reload }
45
+ before { child.reload }
46
+ before { grandchild.reload }
472
47
 
473
- it 'should not discard orphaned nodes by default' do
474
- relation = root.descendants.where(root.class.arel_table[:id].not_eq(child_1.id))
48
+ it { expect(root.level).to eq 0 }
49
+ it { expect{root.level}.not_to query_database }
475
50
 
476
- expect(relation.arrange).to eq Hash[
477
- grandchild_11 => {},
478
- grandchild_12 => {},
479
- child_2 => {
480
- grandchild_21 => {},
481
- grandchild_22 => {}
482
- }
483
- ]
484
- end
51
+ it { expect(child.level).to eq 1 }
52
+ it { expect{child.level}.to query_database.once }
485
53
 
486
- it 'should discard orphans if option :discard passed' do
487
- relation = root.descendants.where(root.class.arel_table[:id].not_eq(child_1.id))
54
+ it { expect(grandchild.level).to eq 2 }
55
+ it { expect{grandchild.level}.to query_database.at_least(:once) }
488
56
 
489
- expect(relation.arrange(:orphans => :discard)).to eq Hash[
490
- child_2 => {
491
- grandchild_21 => {},
492
- grandchild_22 => {}
493
- }
494
- ]
495
- end
496
- end
57
+ context 'given a record with already loaded parent' do
58
+ before { child.association(:parent).load_target }
59
+ before { grandchild.parent.association(:parent).load_target }
497
60
 
498
- context 'when persisted tree given' do
499
- it_should_behave_like 'arrangeable' do
500
- let(:root) { create :default }
61
+ it { expect(child.level).to eq 1 }
62
+ it { expect{child.level}.not_to query_database }
501
63
 
502
- before { create_list :default, 2, :parent => root }
503
- before { create_list :default, 2, :parent => root.children.first }
504
- before { create_list :default, 2, :parent => root.children.last }
64
+ it { expect(grandchild.level).to eq 2 }
65
+ it { expect{grandchild.level}.not_to query_database }
505
66
  end
506
67
  end
507
68
  end
508
69
 
509
- describe "move actions" do
510
- let!(:root) { create :default_with_counter_cache, :name => 'root' }
511
- let!(:child_1) { create :default_with_counter_cache, :parent => root, :name => 'child_1' }
512
- let!(:child_2) { create :default_with_counter_cache, :parent => root, :name => 'child_2' }
513
- let!(:child_3) { create :default_with_counter_cache, :parent => root, :name => 'child_3' }
514
- let!(:child_4) { create :default_with_counter_cache, :parent => child_3, :name => 'child_4' }
515
-
516
- context "initial" do
517
- specify { expect([child_1, child_2, child_3]).to be_sorted }
518
-
519
- subject { root.reload }
520
- its(:parent_id) { should be_nil }
521
- its(:level) { should be_zero }
522
- its(:position) { should eq 1 }
523
- its(:categories_count) { should eq 3}
524
- end
525
-
526
- context "on_save_when_parent_changed" do
527
- example "move_1_to_root" do
528
- child_1.parent = nil
529
- expect{ child_1.save! }.to_not raise_exception
530
- expect(child_1.position).to eq 2
531
- expect([root, child_1]).to be_sorted
532
- end
533
-
534
- example "move_3_to_root" do
535
- child_3.parent = nil
536
- expect{ child_3.save! }.to_not raise_exception
537
- expect(child_3.position).to eq 2
538
- expect([root, child_3]).to be_sorted
539
-
540
- expect(child_3.reload.level).to eq 0
541
- expect(child_4.reload.level).to eq 1
542
- end
543
-
544
- example "move_grandchild" do
545
- grandchild = FactoryGirl.create(:default_with_counter_cache, :parent => child_3)
546
- grandchild.parent = child_2
547
- expect{ grandchild.save! }.to_not raise_exception
548
- expect([grandchild]).to eq child_2.children
549
- end
550
- end
551
-
552
- describe "#move_left" do
553
- example "move_1_left" do
554
- expect{ child_1.move_left }.to raise_exception ActiveRecord::ActiveRecordError
555
- expect([child_1, child_2, child_3]).to be_sorted
556
- end
557
-
558
- example "move_2_left" do
559
- child_2.move_left
560
- expect([child_2, child_1, child_3]).to be_sorted
561
- end
562
-
563
- example "move_3_left" do
564
- child_3.move_left
565
- expect([child_1, child_3, child_2]).to be_sorted
566
- end
567
- end
568
-
569
- describe "#move_right" do
570
- example "move_3_right" do
571
- expect{ child_3.move_right }.to raise_exception ActiveRecord::ActiveRecordError
572
- expect([child_1, child_2, child_3]).to be_sorted
573
- end
574
-
575
- example "move_2_right" do
576
- child_2.move_right
577
- expect([child_1, child_3, child_2]).to be_sorted
578
- end
579
-
580
- example "move_1_right" do
581
- child_1.move_right
582
- expect([child_2, child_1, child_3]).to be_sorted
583
- end
584
- end
585
-
586
- describe "#move_to_left_of" do
587
- example "move_3_to_left_of_1" do
588
- child_3.move_to_left_of child_1
589
- expect([child_3, child_1, child_2]).to be_sorted
590
- end
591
-
592
- example "move_3_to_left_of_2" do
593
- child_3.move_to_left_of child_2
594
- expect([child_1, child_3, child_2]).to be_sorted
595
- end
596
-
597
- example "move_1_to_left_of_3" do
598
- child_1.move_to_left_of child_3
599
- expect([child_2, child_1, child_3]).to be_sorted
600
- end
601
-
602
- example "move_1_to_left_of_3_id" do
603
- child_1.move_to_left_of child_3.id
604
- expect([child_2, child_1, child_3]).to be_sorted
605
- end
606
-
607
- example "move_root_to_left_of_child_2" do
608
- expect{ root.move_to_left_of child_2 }.to raise_exception ActiveRecord::ActiveRecordError
609
- end
610
- end
611
-
612
- describe "#move_to_right_of" do
613
- example "move_1_to_right_of_2" do
614
- child_1.move_to_right_of child_2
615
- expect([child_2, child_1, child_3]).to be_sorted
616
- end
617
-
618
- example "move_1_to_right_of_3" do
619
- child_1.move_to_right_of child_3
620
- expect([child_2, child_3, child_1]).to be_sorted
621
- end
622
-
623
- example "move_1_to_right_of_3_id" do
624
- child_1.move_to_right_of child_3.id
625
- expect([child_2, child_3, child_1]).to be_sorted
626
- end
627
-
628
- example "move_3_to_right_of_1" do
629
- child_3.move_to_right_of child_1
630
- expect([child_1, child_3, child_2]).to be_sorted
631
- end
632
-
633
- example "move_root_to_right_of_child_2" do
634
- expect{ root.move_to_right_of child_2 }.to raise_exception ActiveRecord::ActiveRecordError
635
- end
636
- end
637
-
638
- describe "#move_to_root" do
639
- before { child_2.move_to_root }
640
-
641
- context "child_2" do
642
- subject { child_2 }
643
-
644
- its(:level) { should be_zero }
645
- its(:parent_id) { should be_nil }
646
- its(:position) { should eq 2 }
647
-
648
- it "should not become new root" do
649
- DefaultWithCounterCache.root.should eq root
650
- end
651
- end
652
-
653
- context "other_nodes" do
654
- specify { child_1.reload.position.should eq 1 }
655
- specify { child_3.reload.position.should eq 2 }
656
- specify { root.reload.categories_count.should eq 2 }
657
- end
658
-
659
-
660
- context "given a root node" do
661
- before { root.move_to_root }
662
- subject { root }
663
-
664
- its(:position) { should eq 1 }
665
-
666
- it "positions should not change" do
667
- expect([root, child_3]).to be_sorted
668
- end
669
- end
670
- end
671
-
672
- describe "#move_to_child_of" do
673
- let(:moved_child) { create :default_with_counter_cache, :name => 'moved_child' }
674
-
675
- before { moved_child.move_to_child_of root }
676
- context "moved_child" do
677
- subject { moved_child }
678
- its(:level) { should eq 1 }
679
- its(:position) { should eq 4 }
680
- end
681
-
682
- context "root" do
683
- subject { root.reload }
684
- its(:right_sibling) { should be_nil }
685
- its(:categories_count) { should eq 4 }
686
- end
687
-
688
- context "given a node which already is children of target" do
689
- subject { child_2 }
690
- before { child_2.move_to_child_of root }
691
-
692
- its(:position) { should eq 2 }
693
-
694
- it "positions_should_not_change" do
695
- expect([child_1, child_2, child_3, moved_child]).to be_sorted
696
- end
697
- end
698
-
699
- it { expect([child_1, child_2, child_3, moved_child]).to be_sorted }
700
- it { expect{ root.move_to_child_of root }.to raise_exception ActiveRecord::ActiveRecordError }
701
- it { expect{ root.move_to_child_of child_1 }.to raise_exception ActiveRecord::ActiveRecordError }
702
-
703
- context "when node with descendants moved and depth is changed" do
704
- before { child_3.move_to_child_of child_2 }
705
- before { child_4.reload }
706
-
707
- it "changes parent of child_3" do
708
- expect(child_3.parent).to eq child_2
709
- end
710
-
711
- it "moves to the end of new parents children list" do
712
- expect(child_3).to be_last
713
- end
714
-
715
- it "changes depth of child_3 descendants" do
716
- expect(child_4.level).to eq 3
717
- end
718
- end
719
- end
720
-
721
- describe "#move_to_child_with_index" do
722
- let(:moved_child) { create :default, :name => 'moved_child' }
723
-
724
- example "move_to_child_as_first" do
725
- moved_child.move_to_child_with_index root, 0
726
- expect([moved_child, child_1, child_2, child_3]).to be_sorted
727
- moved_child.position.should eq 1
728
- end
729
-
730
- example "move_to_child_as_second" do
731
- moved_child.move_to_child_with_index root, 1
732
- expect([child_1, moved_child, child_2, child_3]).to be_sorted
733
- moved_child.position.should eq 2
734
- end
735
-
736
- example "move_to_child_as_third" do
737
- moved_child.move_to_child_with_index root, 2
738
- expect([child_1, child_2, moved_child, child_3]).to be_sorted
739
- moved_child.position.should eq 3
740
- end
741
-
742
- example "move_to_child_as_last" do
743
- moved_child.move_to_child_with_index root, 3
744
- expect([child_1, child_2, child_3, moved_child]).to be_sorted
745
- moved_child.position.should eq 4
746
- end
747
-
748
- example "move_child_to_root_as_first" do
749
- child_3.move_to_child_with_index nil, 0
750
- child_3.level.should be_zero
751
- expect([child_3, root, moved_child]).to be_sorted
752
- expect([child_1, child_2]).to be_sorted
753
- child_2.right_sibling.should be_nil
754
- end
755
-
756
- example "move_to_child_with_large_index" do
757
- moved_child.move_to_child_with_index root, 100
758
- expect([child_1, child_2, child_3, moved_child]).to be_sorted
759
- moved_child.position.should eq 4
760
- end
761
-
762
- example "move_to_child_with_negative_index" do
763
- moved_child.move_to_child_with_index root, -2
764
- expect([child_1, child_2, moved_child, child_3]).to be_sorted
765
- moved_child.position.should eq 3
766
- end
767
-
768
- example "move_to_child_with_large_negative_index" do
769
- expect{ moved_child.move_to_child_with_index root, -100 }.to raise_exception ActiveRecord::ActiveRecordError
770
- end
771
-
772
- example "move_to_child_with_nil_index" do
773
- expect{ moved_child.move_to_child_with_index root, nil }.to raise_exception ActiveRecord::ActiveRecordError
774
- end
775
-
776
- example "move_to_child_with_float_index" do
777
- moved_child.move_to_child_with_index root, 1.7
778
- expect([child_1, moved_child, child_2, child_3]).to be_sorted
779
- end
780
-
781
- example "move_root_to_child_of_self" do
782
- expect{ root.move_to_child_with_index child_1, 1 }.to raise_exception ActiveRecord::ActiveRecordError
783
- end
784
-
785
- context "with scoped tree" do
786
- let!(:root1) { create :scoped, :scope_type => 's1' }
787
- let!(:node1) { create :scoped, :scope_type => 's1', :parent => root1 }
788
- let!(:root2) { create :scoped, :scope_type => 's2' }
789
- let!(:node2) { create :scoped, :scope_type => 's2', :parent => root2 }
790
-
791
- example "move_node1_to_root" do
792
- node1.should_receive(:move_to_right_of).with(root1)
793
- node1.move_to_child_with_index nil, 100
794
- end
795
-
796
- example "move_node2_to_root" do
797
- node2.should_receive(:move_to_right_of).with(root2)
798
- node2.move_to_child_with_index nil, 100
799
- end
800
- end
801
-
70
+ describe 'move actions' do
71
+ tree :factory => :default_with_counter_cache do
72
+ root {
73
+ child_1
74
+ child_2 :name => 'child_2'
75
+ child_3 {
76
+ child_4
77
+ }
78
+ }
802
79
  end
803
80
 
804
- describe "#insert_at" do
805
- before { child_3.insert_at(1) }
81
+ describe '#insert_at' do
82
+ before { ActiveSupport::Deprecation.silence { child_3.insert_at(1) } }
806
83
  before { child_3.reload }
807
84
 
808
85
  specify { expect([child_3, child_1, child_2]).to be_sorted }
809
86
  end
87
+ end
810
88
 
811
- describe "callbacks" do
812
- subject { child_3 }
813
-
814
- it { should fire_callback(:before_move).when_calling(:move_to_root).once }
815
- it { should fire_callback(:after_move).when_calling(:move_to_root).once }
816
- it { should fire_callback(:around_move).when_calling(:move_to_root).once }
817
-
818
- it { should_not fire_callback(:before_move).when_calling(:move_left) }
819
- it { should_not fire_callback(:after_move).when_calling(:move_left) }
820
- it { should_not fire_callback(:around_move).when_calling(:move_left) }
821
-
822
- it { should fire_callback(:before_reorder).when_calling(:move_higher).once }
823
- it { should fire_callback(:after_reorder).when_calling(:move_higher).once }
824
-
825
- it { should_not fire_callback(:before_reorder).when_calling(:move_to_root) }
826
-
827
- it "should cache depth on save" do
828
- record = build :default_with_counter_cache
829
-
830
- record.depth.should be_nil
831
- record.save
832
-
833
- record.depth.should eq 0
834
-
835
- record.move_to_left_of child_3
836
- record.depth.should eq child_3.level
837
- end
838
-
839
- it "should recalculate depth of descendants" do
840
- record = create :default_with_counter_cache, :parent => child_3
841
- record.depth.should eq 2
842
-
843
- child_3.move_to_root
844
- record.reload.depth.should eq 1
845
-
846
- child_3.move_to_child_of child_1
847
- record.reload.depth.should eq 3
848
- end
849
-
850
- context "DefaultWithCallbacks" do
851
- let!(:cb_root_1) { create :default_with_callbacks, :name => 'root_1' }
852
- let!(:cb_root_2) { create :default_with_callbacks, :name => 'root_2' }
853
- let!(:cb_child_1) { create :default_with_callbacks, :name => 'child_1', :parent => cb_root_1 }
854
- let!(:cb_child_2) { create :default_with_callbacks, :name => 'child_2', :parent => cb_root_1 }
855
-
856
- specify "new parent_id should be available in before_move" do
857
- cb_root_2.stub(:before_move) { cb_root_2.parent_id.should eq cb_root_1.id }
858
- cb_root_2.move_to_left_of cb_child_1
859
- end
860
-
861
- specify "new position should be available in before_reorder" do
862
- cb_child_2.stub(:before_reorder) { cb_child_2.position.should eq 1 }
863
- cb_child_2.move_to_left_of cb_child_1
864
- end
89
+ describe 'scoped trees' do
90
+ tree :factory => :scoped do
91
+ root1 :scope_type => 't1' do
92
+ child1
93
+ orphan
865
94
  end
866
-
867
- end
868
-
869
- context "changed attributes" do
870
- before do
871
- child_2.name = 'changed_100'
872
- child_2.move_to_left_of child_1
95
+ root2 :scope_type => 't2' do
96
+ child2
873
97
  end
874
-
875
- it { child_2.reload.name.should eq 'child_2' }
876
- end
877
-
878
- end
879
-
880
- describe "scoped trees" do
881
- let!(:root1) { create :scoped, :scope_type => "t1" }
882
- let!(:child1) { create :scoped, :parent => root1 }
883
- let!(:orphan) do
884
- record = create :scoped, :parent => root1
885
- record.class.where(:id => record.id).update_all(:scope_type => "t0", :position => 1)
886
- record
887
98
  end
888
99
 
889
- let!(:root2) { create :scoped, :scope_type => "t2" }
890
- let!(:child2) { create :scoped, :scope_type => "t2", :parent => root2 }
100
+ before { Scoped.where(:id => orphan.id).update_all(:scope_type => 't0', :position => 1) }
891
101
 
892
- it "should not stick positions together for different scopes" do
893
- root1.position.should eq root2.position
102
+ it 'should not stick positions together for different scopes' do
103
+ expect(root1.position).to eq root2.position
894
104
  end
895
- it "should automatically set scope for new records with parent" do
896
- child1.should be_same_scope(root1)
105
+ it 'should automatically set scope for new records with parent' do
106
+ expect(child1.ordered_tree_node).to be_same_scope root1
897
107
  end
898
- it "should not include orphans" do
899
- root1.children.reload.should_not include orphan
900
- root1.descendants.reload.should_not include orphan
108
+ it 'should not include orphans' do
109
+ expect(root1.children.reload).not_to include orphan
110
+ expect(root1.descendants.reload).not_to include orphan
901
111
  end
902
- it "should not allow to move records between scopes" do
903
- expect { child2.move_to_child_of root1 }.to raise_error(ActiveRecord::ActiveRecordError)
112
+ it 'should not allow to move records between scopes' do
113
+ expect(child2.move_to_child_of(root1)).to be false
114
+ expect(child2.errors_on(:parent).size).to be >= 1
904
115
  end
905
- it "should not allow to change scope" do
116
+ it 'should not allow to change scope' do
906
117
  child2.parent = root1
907
- child2.should have_at_least(1).error_on(:parent)
118
+ expect(child2.errors_on(:parent).size).to be >= 1
908
119
  end
909
- it "should not allow to add scoped record to children collection" do
120
+ it 'should not allow to add scoped record to children collection' do
910
121
  root1.children << child2
911
- root1.children.reload.should_not include child2
912
- end
913
- end
914
-
915
- describe "#destroy behavior" do
916
- let!(:root) { create :default_with_counter_cache, :name => 'root' }
917
- let!(:child_1) { create :default_with_counter_cache, :parent => root, :name => 'child_1' }
918
- let!(:child_2) { create :default_with_counter_cache, :parent => root, :name => 'child_2' }
919
- let!(:child_3) { create :default_with_counter_cache, :parent => root, :name => 'child_3' }
920
-
921
- describe "it should destroy descendants" do
922
- subject { root }
923
- before { subject.destroy }
924
-
925
- it { should be_destroyed }
926
- its('descendants.reload') { should be_empty }
927
-
928
- specify "ensure the loneliness" do
929
- root.class.all.should be_empty
930
- end
931
- end
932
-
933
- describe "it should stick positions together" do
934
- before { child_2.destroy }
935
- before { child_3.reload }
936
-
937
- subject { child_3 }
938
-
939
- its(:left_sibling) { should eq child_1 }
940
- its(:position) { should eq 2 }
941
-
942
- specify "root categories_count should decrease" do
943
- root.reload.categories_count.should eq 2
944
- end
122
+ expect(root1.children.reload).not_to include child2
945
123
  end
946
124
  end
947
125
 
@@ -956,32 +134,25 @@ describe ActsAsOrderedTree, :transactional do
956
134
  context "given self as parent" do
957
135
  before { root.parent = root }
958
136
 
959
- it { should have_at_least(1).error_on(:parent) }
137
+ it 'has at least 1 error_on' do
138
+ expect(subject.error_on(:parent).size).to be >= 1
139
+ end
960
140
  end
961
141
 
962
142
  context "given child as parent" do
963
143
  before { root.parent = child }
964
144
 
965
- it { should have_at_least(1).error_on(:parent) }
145
+ it 'has at least 1 error_on' do
146
+ expect(subject.error_on(:parent).size).to be >= 1
147
+ end
966
148
  end
967
149
 
968
150
  context "given grandchild as parent" do
969
151
  before { root.parent = grandchild }
970
152
 
971
- it { should have_at_least(1).error_on(:parent) }
972
- end
973
- end
974
-
975
- describe "attempt to create node with wrong position" do
976
- it "should not throw error" do
977
- expect{ create :default, :position => 22 }.not_to raise_error
978
- end
979
-
980
- it "should be saved at proper position" do
981
- root = create :default
982
-
983
- node = create :default, :position => 2
984
- node.position.should eq 2
153
+ it 'has at least 1 error_on' do
154
+ expect(subject.error_on(:parent).size).to be >= 1
155
+ end
985
156
  end
986
157
  end
987
158
  end