acts_as_ordered_tree 1.3.1 → 2.0.0.beta3

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.
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