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.
- checksums.yaml +4 -4
- data/lib/acts_as_ordered_tree.rb +22 -100
- data/lib/acts_as_ordered_tree/adapters.rb +17 -0
- data/lib/acts_as_ordered_tree/adapters/abstract.rb +23 -0
- data/lib/acts_as_ordered_tree/adapters/postgresql.rb +150 -0
- data/lib/acts_as_ordered_tree/adapters/recursive.rb +157 -0
- data/lib/acts_as_ordered_tree/compatibility.rb +22 -0
- data/lib/acts_as_ordered_tree/compatibility/active_record/association_scope.rb +9 -0
- data/lib/acts_as_ordered_tree/compatibility/active_record/default_scoped.rb +19 -0
- data/lib/acts_as_ordered_tree/compatibility/active_record/null_relation.rb +71 -0
- data/lib/acts_as_ordered_tree/compatibility/features.rb +153 -0
- data/lib/acts_as_ordered_tree/deprecate.rb +24 -0
- data/lib/acts_as_ordered_tree/hooks.rb +38 -0
- data/lib/acts_as_ordered_tree/hooks/update.rb +86 -0
- data/lib/acts_as_ordered_tree/instance_methods.rb +92 -453
- data/lib/acts_as_ordered_tree/iterators/arranger.rb +35 -0
- data/lib/acts_as_ordered_tree/iterators/level_calculator.rb +52 -0
- data/lib/acts_as_ordered_tree/iterators/orphans_pruner.rb +58 -0
- data/lib/acts_as_ordered_tree/node.rb +78 -0
- data/lib/acts_as_ordered_tree/node/attributes.rb +48 -0
- data/lib/acts_as_ordered_tree/node/movement.rb +62 -0
- data/lib/acts_as_ordered_tree/node/movements.rb +111 -0
- data/lib/acts_as_ordered_tree/node/predicates.rb +98 -0
- data/lib/acts_as_ordered_tree/node/reloading.rb +49 -0
- data/lib/acts_as_ordered_tree/node/siblings.rb +139 -0
- data/lib/acts_as_ordered_tree/node/traversals.rb +53 -0
- data/lib/acts_as_ordered_tree/persevering_transaction.rb +93 -0
- data/lib/acts_as_ordered_tree/position.rb +143 -0
- data/lib/acts_as_ordered_tree/relation/arrangeable.rb +33 -0
- data/lib/acts_as_ordered_tree/relation/iterable.rb +41 -0
- data/lib/acts_as_ordered_tree/relation/preloaded.rb +46 -11
- data/lib/acts_as_ordered_tree/transaction/base.rb +57 -0
- data/lib/acts_as_ordered_tree/transaction/callbacks.rb +67 -0
- data/lib/acts_as_ordered_tree/transaction/create.rb +68 -0
- data/lib/acts_as_ordered_tree/transaction/destroy.rb +34 -0
- data/lib/acts_as_ordered_tree/transaction/dsl.rb +214 -0
- data/lib/acts_as_ordered_tree/transaction/factory.rb +67 -0
- data/lib/acts_as_ordered_tree/transaction/move.rb +70 -0
- data/lib/acts_as_ordered_tree/transaction/passthrough.rb +12 -0
- data/lib/acts_as_ordered_tree/transaction/reorder.rb +42 -0
- data/lib/acts_as_ordered_tree/transaction/save.rb +64 -0
- data/lib/acts_as_ordered_tree/transaction/update.rb +78 -0
- data/lib/acts_as_ordered_tree/tree.rb +148 -0
- data/lib/acts_as_ordered_tree/tree/association.rb +20 -0
- data/lib/acts_as_ordered_tree/tree/callbacks.rb +57 -0
- data/lib/acts_as_ordered_tree/tree/children_association.rb +120 -0
- data/lib/acts_as_ordered_tree/tree/columns.rb +102 -0
- data/lib/acts_as_ordered_tree/tree/deprecated_columns_accessors.rb +24 -0
- data/lib/acts_as_ordered_tree/tree/parent_association.rb +31 -0
- data/lib/acts_as_ordered_tree/tree/perseverance.rb +19 -0
- data/lib/acts_as_ordered_tree/tree/scopes.rb +56 -0
- data/lib/acts_as_ordered_tree/validators.rb +1 -1
- data/lib/acts_as_ordered_tree/version.rb +1 -1
- data/spec/acts_as_ordered_tree_spec.rb +80 -909
- data/spec/adapters/postgresql_spec.rb +14 -0
- data/spec/adapters/recursive_spec.rb +12 -0
- data/spec/adapters/shared.rb +272 -0
- data/spec/callbacks_spec.rb +177 -0
- data/spec/counter_cache_spec.rb +31 -0
- data/spec/create_spec.rb +110 -0
- data/spec/destroy_spec.rb +57 -0
- data/spec/inheritance_spec.rb +176 -0
- data/spec/move_spec.rb +94 -0
- data/spec/node/movements/concurrent_movements_spec.rb +354 -0
- data/spec/node/movements/move_higher_spec.rb +46 -0
- data/spec/node/movements/move_lower_spec.rb +46 -0
- data/spec/node/movements/move_to_child_of_spec.rb +147 -0
- data/spec/node/movements/move_to_child_with_index_spec.rb +124 -0
- data/spec/node/movements/move_to_child_with_position_spec.rb +85 -0
- data/spec/node/movements/move_to_left_of_spec.rb +120 -0
- data/spec/node/movements/move_to_right_of_spec.rb +120 -0
- data/spec/node/movements/move_to_root_spec.rb +67 -0
- data/spec/node/predicates_spec.rb +211 -0
- data/spec/node/reloading_spec.rb +42 -0
- data/spec/node/siblings_spec.rb +193 -0
- data/spec/node/traversals_spec.rb +71 -0
- data/spec/persevering_transaction_spec.rb +98 -0
- data/spec/relation/arrangeable_spec.rb +88 -0
- data/spec/relation/iterable_spec.rb +104 -0
- data/spec/relation/preloaded_spec.rb +57 -0
- data/spec/reorder_spec.rb +83 -0
- data/spec/spec_helper.rb +30 -38
- data/spec/support/db/boot.rb +22 -0
- data/spec/{db → support/db}/config.travis.yml +2 -0
- data/spec/{db → support/db}/config.yml +1 -0
- data/spec/{db → support/db}/schema.rb +9 -0
- data/spec/support/factories.rb +2 -2
- data/spec/support/matchers.rb +67 -58
- data/spec/support/models.rb +6 -14
- data/spec/support/tree_factory.rb +315 -0
- data/spec/tree/children_association_spec.rb +72 -0
- data/spec/tree/columns_spec.rb +65 -0
- data/spec/tree/scopes_spec.rb +39 -0
- metadata +161 -43
- data/lib/acts_as_ordered_tree/adapters/postgresql_adapter.rb +0 -104
- data/lib/acts_as_ordered_tree/arrangeable.rb +0 -80
- data/lib/acts_as_ordered_tree/class_methods.rb +0 -72
- data/lib/acts_as_ordered_tree/relation/base.rb +0 -26
- data/lib/acts_as_ordered_tree/tenacious_transaction.rb +0 -30
- data/spec/concurrency_support_spec.rb +0 -156
@@ -1,947 +1,125 @@
|
|
1
1
|
require File.expand_path('../spec_helper', __FILE__)
|
2
2
|
|
3
3
|
describe ActsAsOrderedTree, :transactional do
|
4
|
-
|
5
|
-
|
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
|
147
|
-
|
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
|
-
|
12
|
+
it { expect(subject.level).to eq 0 }
|
186
13
|
end
|
187
|
-
|
14
|
+
|
15
|
+
context 'given a new root record' do
|
188
16
|
subject { build :default }
|
189
17
|
|
190
|
-
|
18
|
+
it { expect(subject.level).to eq 0 }
|
191
19
|
end
|
192
|
-
|
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 {
|
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
|
229
|
-
|
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
|
-
|
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
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
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
|
-
|
456
|
-
|
457
|
-
|
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
|
474
|
-
|
48
|
+
it { expect(root.level).to eq 0 }
|
49
|
+
it { expect{root.level}.not_to query_database }
|
475
50
|
|
476
|
-
|
477
|
-
|
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
|
487
|
-
|
54
|
+
it { expect(grandchild.level).to eq 2 }
|
55
|
+
it { expect{grandchild.level}.to query_database.at_least(:once) }
|
488
56
|
|
489
|
-
|
490
|
-
|
491
|
-
|
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
|
-
|
499
|
-
|
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
|
-
|
503
|
-
|
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
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
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
|
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
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
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
|
-
|
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
|
-
|
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
|
893
|
-
root1.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
|
896
|
-
child1.
|
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
|
899
|
-
root1.children.reload.
|
900
|
-
root1.descendants.reload.
|
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
|
903
|
-
expect
|
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
|
116
|
+
it 'should not allow to change scope' do
|
906
117
|
child2.parent = root1
|
907
|
-
child2.
|
118
|
+
expect(child2.errors_on(:parent).size).to be >= 1
|
908
119
|
end
|
909
|
-
it
|
120
|
+
it 'should not allow to add scoped record to children collection' do
|
910
121
|
root1.children << child2
|
911
|
-
root1.children.reload.
|
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
|
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
|
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
|
972
|
-
|
973
|
-
|
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
|