closure_tree 6.5.0 → 7.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +98 -0
  3. data/.gitignore +2 -0
  4. data/.rspec +1 -1
  5. data/Appraisals +90 -7
  6. data/CHANGELOG.md +100 -42
  7. data/Gemfile +3 -11
  8. data/README.md +68 -24
  9. data/Rakefile +16 -10
  10. data/_config.yml +1 -0
  11. data/bin/appraisal +29 -0
  12. data/bin/rake +29 -0
  13. data/bin/rspec +29 -0
  14. data/closure_tree.gemspec +16 -9
  15. data/lib/closure_tree/finders.rb +32 -9
  16. data/lib/closure_tree/has_closure_tree.rb +4 -0
  17. data/lib/closure_tree/has_closure_tree_root.rb +5 -7
  18. data/lib/closure_tree/hash_tree_support.rb +4 -4
  19. data/lib/closure_tree/hierarchy_maintenance.rb +28 -8
  20. data/lib/closure_tree/model.rb +42 -16
  21. data/lib/closure_tree/numeric_deterministic_ordering.rb +20 -6
  22. data/lib/closure_tree/numeric_order_support.rb +7 -3
  23. data/lib/closure_tree/support.rb +18 -12
  24. data/lib/closure_tree/support_attributes.rb +10 -1
  25. data/lib/closure_tree/support_flags.rb +1 -4
  26. data/lib/closure_tree/version.rb +1 -1
  27. data/lib/generators/closure_tree/migration_generator.rb +8 -0
  28. data/lib/generators/closure_tree/templates/create_hierarchies_table.rb.erb +1 -1
  29. metadata +78 -79
  30. data/.travis.yml +0 -29
  31. data/gemfiles/activerecord_4.2.gemfile +0 -19
  32. data/gemfiles/activerecord_5.0.gemfile +0 -19
  33. data/gemfiles/activerecord_5.0_foreigner.gemfile +0 -20
  34. data/gemfiles/activerecord_edge.gemfile +0 -20
  35. data/img/example.png +0 -0
  36. data/img/preorder.png +0 -0
  37. data/spec/cache_invalidation_spec.rb +0 -39
  38. data/spec/cuisine_type_spec.rb +0 -38
  39. data/spec/db/database.yml +0 -21
  40. data/spec/db/models.rb +0 -128
  41. data/spec/db/schema.rb +0 -166
  42. data/spec/fixtures/tags.yml +0 -98
  43. data/spec/generators/migration_generator_spec.rb +0 -48
  44. data/spec/has_closure_tree_root_spec.rb +0 -154
  45. data/spec/hierarchy_maintenance_spec.rb +0 -16
  46. data/spec/label_spec.rb +0 -554
  47. data/spec/matcher_spec.rb +0 -34
  48. data/spec/metal_spec.rb +0 -55
  49. data/spec/model_spec.rb +0 -9
  50. data/spec/namespace_type_spec.rb +0 -13
  51. data/spec/parallel_spec.rb +0 -159
  52. data/spec/spec_helper.rb +0 -24
  53. data/spec/support/database.rb +0 -52
  54. data/spec/support/database_cleaner.rb +0 -14
  55. data/spec/support/exceed_query_limit.rb +0 -18
  56. data/spec/support/hash_monkey_patch.rb +0 -13
  57. data/spec/support/query_counter.rb +0 -18
  58. data/spec/support/sqlite3_with_advisory_lock.rb +0 -10
  59. data/spec/support_spec.rb +0 -14
  60. data/spec/tag_examples.rb +0 -665
  61. data/spec/tag_spec.rb +0 -6
  62. data/spec/user_spec.rb +0 -174
  63. data/spec/uuid_tag_spec.rb +0 -6
data/spec/label_spec.rb DELETED
@@ -1,554 +0,0 @@
1
- require 'spec_helper'
2
-
3
- def create_label_tree
4
- @d1 = Label.find_or_create_by_path %w(a1 b1 c1 d1)
5
- @c1 = @d1.parent
6
- @b1 = @c1.parent
7
- @a1 = @b1.parent
8
- @d2 = Label.find_or_create_by_path %w(a1 b1 c2 d2)
9
- @c2 = @d2.parent
10
- @d3 = Label.find_or_create_by_path %w(a2 b2 c3 d3)
11
- @c3 = @d3.parent
12
- @b2 = @c3.parent
13
- @a2 = @b2.parent
14
- Label.update_all("#{Label._ct.order_column} = id")
15
- end
16
-
17
- def create_preorder_tree(suffix = "", &block)
18
- %w(
19
- a/l/n/r
20
- a/l/n/q
21
- a/l/n/p
22
- a/l/n/o
23
- a/l/m
24
- a/b/h/i/j/k
25
- a/b/c/d/g
26
- a/b/c/d/f
27
- a/b/c/d/e
28
- ).shuffle.each { |ea| Label.find_or_create_by_path(ea.split('/').collect { |ea| "#{ea}#{suffix}" }) }
29
-
30
- Label.roots.each_with_index do |root, root_idx|
31
- root.order_value = root_idx
32
- yield(root) if block_given?
33
- root.save!
34
- root.self_and_descendants.each do |ea|
35
- ea.children.to_a.sort_by(&:name).each_with_index do |ea, idx|
36
- ea.order_value = idx
37
- yield(ea) if block_given?
38
- ea.save!
39
- end
40
- end
41
- end
42
- end
43
-
44
- describe Label do
45
- context "destruction" do
46
- it "properly destroys descendents created with find_or_create_by_path" do
47
- c = Label.find_or_create_by_path %w(a b c)
48
- b = c.parent
49
- a = c.root
50
- a.destroy
51
- expect(Label.exists?(id: [a.id, b.id, c.id])).to be_falsey
52
- end
53
-
54
- it "properly destroys descendents created with add_child" do
55
- a = Label.create(name: 'a')
56
- b = a.add_child Label.new(name: 'b')
57
- c = b.add_child Label.new(name: 'c')
58
- a.destroy
59
- expect(Label.exists?(a.id)).to be_falsey
60
- expect(Label.exists?(b.id)).to be_falsey
61
- expect(Label.exists?(c.id)).to be_falsey
62
- end
63
-
64
- it "properly destroys descendents created with <<" do
65
- a = Label.create(name: 'a')
66
- b = Label.new(name: 'b')
67
- a.children << b
68
- c = Label.new(name: 'c')
69
- b.children << c
70
- a.destroy
71
- expect(Label.exists?(a.id)).to be_falsey
72
- expect(Label.exists?(b.id)).to be_falsey
73
- expect(Label.exists?(c.id)).to be_falsey
74
- end
75
- end
76
-
77
- context "roots" do
78
- it "sorts alphabetically" do
79
- expected = (0..10).to_a
80
- expected.shuffle.each do |ea|
81
- Label.create! do |l|
82
- l.name = "root #{ea}"
83
- l.order_value = ea
84
- end
85
- end
86
- expect(Label.roots.collect { |ea| ea.order_value }).to eq(expected)
87
- end
88
- end
89
-
90
- context "Base Label class" do
91
- it "should find or create by path" do
92
- # class method:
93
- c = Label.find_or_create_by_path(%w{grandparent parent child})
94
- expect(c.ancestry_path).to eq(%w{grandparent parent child})
95
- expect(c.name).to eq("child")
96
- expect(c.parent.name).to eq("parent")
97
- end
98
- end
99
-
100
- context "Parent/child inverse relationships" do
101
- it "should associate both sides of the parent and child relationships" do
102
- parent = Label.new(:name => 'parent')
103
- child = parent.children.build(:name => 'child')
104
- expect(parent).to be_root
105
- expect(parent).not_to be_leaf
106
- expect(child).not_to be_root
107
- expect(child).to be_leaf
108
- end
109
- end
110
-
111
- context "DateLabel" do
112
- it "should find or create by path" do
113
- date = DateLabel.find_or_create_by_path(%w{2011 November 23})
114
- expect(date.ancestry_path).to eq(%w{2011 November 23})
115
- date.self_and_ancestors.each { |ea| expect(ea.class).to eq(DateLabel) }
116
- expect(date.name).to eq("23")
117
- expect(date.parent.name).to eq("November")
118
- end
119
- end
120
-
121
- context "DirectoryLabel" do
122
- it "should find or create by path" do
123
- dir = DirectoryLabel.find_or_create_by_path(%w{grandparent parent child})
124
- expect(dir.ancestry_path).to eq(%w{grandparent parent child})
125
- expect(dir.name).to eq("child")
126
- expect(dir.parent.name).to eq("parent")
127
- expect(dir.parent.parent.name).to eq("grandparent")
128
- expect(dir.root.name).to eq("grandparent")
129
- expect(dir.id).not_to eq(Label.find_or_create_by_path(%w{grandparent parent child}))
130
- dir.self_and_ancestors.each { |ea| expect(ea.class).to eq(DirectoryLabel) }
131
- end
132
- end
133
-
134
- context "Mixed class tree" do
135
- context "preorder tree" do
136
- before do
137
- classes = [Label, DateLabel, DirectoryLabel, EventLabel]
138
- create_preorder_tree do |ea|
139
- ea.type = classes[ea.order_value % 4].to_s
140
- end
141
- end
142
- it "finds roots with specific classes" do
143
- expect(Label.roots).to eq(Label.where(:name => 'a').to_a)
144
- expect(DirectoryLabel.roots).to be_empty
145
- expect(EventLabel.roots).to be_empty
146
- end
147
-
148
- it "all is limited to subclasses" do
149
- expect(DateLabel.all.map(&:name)).to match_array(%w(f h l n p))
150
- expect(DirectoryLabel.all.map(&:name)).to match_array(%w(g q))
151
- expect(EventLabel.all.map(&:name)).to eq(%w(r))
152
- end
153
-
154
- it "returns descendents regardless of subclass" do
155
- expect(Label.root.descendants.map { |ea| ea.class.to_s }.uniq).to match_array(
156
- %w(Label DateLabel DirectoryLabel EventLabel)
157
- )
158
- end
159
- end
160
-
161
- it "supports children << and add_child" do
162
- a = EventLabel.create!(:name => "a")
163
- b = DateLabel.new(:name => "b")
164
- a.children << b
165
- c = Label.new(:name => "c")
166
- b.add_child(c)
167
-
168
- expect(a.self_and_descendants.collect do |ea|
169
- ea.class
170
- end).to eq([EventLabel, DateLabel, Label])
171
-
172
- expect(a.self_and_descendants.collect do |ea|
173
- ea.name
174
- end).to eq(%w(a b c))
175
- end
176
- end
177
-
178
- context "find_all_by_generation" do
179
- before :each do
180
- create_label_tree
181
- end
182
-
183
- it "finds roots from the class method" do
184
- expect(Label.find_all_by_generation(0).to_a).to eq([@a1, @a2])
185
- end
186
-
187
- it "finds roots from themselves" do
188
- expect(@a1.find_all_by_generation(0).to_a).to eq([@a1])
189
- end
190
-
191
- it "finds itself for non-roots" do
192
- expect(@b1.find_all_by_generation(0).to_a).to eq([@b1])
193
- end
194
-
195
- it "finds children for roots" do
196
- expect(Label.find_all_by_generation(1).to_a).to eq([@b1, @b2])
197
- end
198
-
199
- it "finds children" do
200
- expect(@a1.find_all_by_generation(1).to_a).to eq([@b1])
201
- expect(@b1.find_all_by_generation(1).to_a).to eq([@c1, @c2])
202
- end
203
-
204
- it "finds grandchildren for roots" do
205
- expect(Label.find_all_by_generation(2).to_a).to eq([@c1, @c2, @c3])
206
- end
207
-
208
- it "finds grandchildren" do
209
- expect(@a1.find_all_by_generation(2).to_a).to eq([@c1, @c2])
210
- expect(@b1.find_all_by_generation(2).to_a).to eq([@d1, @d2])
211
- end
212
-
213
- it "finds great-grandchildren for roots" do
214
- expect(Label.find_all_by_generation(3).to_a).to eq([@d1, @d2, @d3])
215
- end
216
- end
217
-
218
- context "loading through self_and_ scopes" do
219
- before :each do
220
- create_label_tree
221
- end
222
-
223
- it "self_and_descendants should result in one select" do
224
- expect(count_queries do
225
- a1_array = @a1.self_and_descendants
226
- expect(a1_array.collect { |ea| ea.name }).to eq(%w(a1 b1 c1 c2 d1 d2))
227
- end).to eq(1)
228
- end
229
-
230
- it "self_and_ancestors should result in one select" do
231
- expect(count_queries do
232
- d1_array = @d1.self_and_ancestors
233
- expect(d1_array.collect { |ea| ea.name }).to eq(%w(d1 c1 b1 a1))
234
- end).to eq(1)
235
- end
236
- end
237
-
238
- context "deterministically orders with polymorphic siblings" do
239
- before :each do
240
- @parent = Label.create!(:name => 'parent')
241
- @a, @b, @c, @d, @e, @f = ('a'..'f').map { |ea| EventLabel.new(:name => ea) }
242
- @parent.children << @a
243
- @a.append_sibling(@b)
244
- @b.append_sibling(@c)
245
- @c.append_sibling(@d)
246
- @parent.append_sibling(@e)
247
- @e.append_sibling(@f)
248
- end
249
-
250
- def name_and_order(enum)
251
- enum.map { |ea| [ea.name, ea.order_value] }
252
- end
253
-
254
- def children_name_and_order
255
- name_and_order(@parent.children.reload)
256
- end
257
-
258
- def roots_name_and_order
259
- name_and_order(Label.roots)
260
- end
261
-
262
- it 'order_values properly' do
263
- expect(children_name_and_order).to eq([['a', 0], ['b', 1], ['c', 2], ['d', 3]])
264
- end
265
-
266
- it 'when inserted before' do
267
- @b.append_sibling(@a)
268
- expect(children_name_and_order).to eq([['b', 0], ['a', 1], ['c', 2], ['d', 3]])
269
- end
270
-
271
- it 'when inserted after' do
272
- @a.append_sibling(@c)
273
- expect(children_name_and_order).to eq([['a', 0], ['c', 1], ['b', 2], ['d', 3]])
274
- end
275
-
276
- it 'when inserted before the first' do
277
- @a.prepend_sibling(@d)
278
- expect(children_name_and_order).to eq([['d', 0], ['a', 1], ['b', 2], ['c', 3]])
279
- end
280
-
281
- it 'when inserted after the last' do
282
- @d.append_sibling(@b)
283
- expect(children_name_and_order).to eq([['a', 0], ['c', 1], ['d', 2], ['b', 3]])
284
- end
285
-
286
- it 'prepends to root nodes' do
287
- @parent.prepend_sibling(@f)
288
- expect(roots_name_and_order).to eq([['f', 0], ['parent', 1], ['e', 2]])
289
- end
290
- end
291
-
292
- describe 'code in the readme' do
293
- it 'creates STI label hierarchies' do
294
- child = Label.find_or_create_by_path([
295
- {type: 'DateLabel', name: '2014'},
296
- {type: 'DateLabel', name: 'August'},
297
- {type: 'DateLabel', name: '5'},
298
- {type: 'EventLabel', name: 'Visit the Getty Center'}
299
- ])
300
- expect(child).to be_a(EventLabel)
301
- expect(child.name).to eq('Visit the Getty Center')
302
- expect(child.ancestors.map(&:name)).to eq(%w(5 August 2014))
303
- expect(child.ancestors.map(&:class)).to eq([DateLabel, DateLabel, DateLabel])
304
- end
305
-
306
- it 'appends and prepends siblings' do
307
- root = Label.create(name: 'root')
308
- a = root.append_child(Label.new(name: 'a'))
309
- b = Label.create(name: 'b')
310
- c = Label.create(name: 'c')
311
-
312
- a.append_sibling(b)
313
- expect(a.self_and_siblings.collect(&:name)).to eq(%w(a b))
314
- expect(root.reload.children.collect(&:name)).to eq(%w(a b))
315
- expect(root.children.collect(&:order_value)).to eq([0, 1])
316
-
317
- a.prepend_sibling(b)
318
- expect(a.self_and_siblings.collect(&:name)).to eq(%w(b a))
319
- expect(root.reload.children.collect(&:name)).to eq(%w(b a))
320
- expect(root.children.collect(&:order_value)).to eq([0, 1])
321
-
322
- a.append_sibling(c)
323
- expect(a.self_and_siblings.collect(&:name)).to eq(%w(b a c))
324
- expect(root.reload.children.collect(&:name)).to eq(%w(b a c))
325
- expect(root.children.collect(&:order_value)).to eq([0, 1, 2])
326
-
327
- # We need to reload b because it was updated by a.append_sibling(c)
328
- b.reload.append_sibling(c)
329
- expect(root.reload.children.collect(&:name)).to eq(%w(b c a))
330
- expect(root.children.collect(&:order_value)).to eq([0, 1, 2])
331
-
332
- # We need to reload a because it was updated by b.append_sibling(c)
333
- d = a.reload.append_sibling(Label.new(:name => "d"))
334
- expect(d.self_and_siblings.collect(&:name)).to eq(%w(b c a d))
335
- expect(d.self_and_siblings.collect(&:order_value)).to eq([0, 1, 2, 3])
336
- end
337
- end
338
-
339
- # https://github.com/mceachen/closure_tree/issues/84
340
- it "properly appends children with <<" do
341
- root = Label.create(:name => "root")
342
- a = Label.create(:name => "a", :parent => root)
343
- b = Label.create(:name => "b", :parent => root)
344
- expect(a.order_value).to eq(0)
345
- expect(b.order_value).to eq(1)
346
- #c = Label.create(:name => "c")
347
-
348
- # should the order_value for roots be set?
349
- expect(root.order_value).not_to be_nil
350
- expect(root.order_value).to eq(0)
351
-
352
- # order_value should never be nil on a child.
353
- expect(a.order_value).not_to be_nil
354
- expect(a.order_value).to eq(0)
355
- # Add a child to root at end of children.
356
- root.children << b
357
- expect(b.parent).to eq(root)
358
- expect(a.self_and_siblings.collect(&:name)).to eq(%w(a b))
359
- expect(root.reload.children.collect(&:name)).to eq(%w(a b))
360
- expect(root.children.collect(&:order_value)).to eq([0, 1])
361
- end
362
-
363
- context "#add_sibling" do
364
- it "should move a node before another node which has an uninitialized order_value" do
365
- f = Label.find_or_create_by_path %w(a b c d e fa)
366
- f0 = f.prepend_sibling(Label.new(:name => "fb")) # < not alpha sort, so name shouldn't matter
367
- expect(f0.ancestry_path).to eq(%w(a b c d e fb))
368
- expect(f.siblings_before.to_a).to eq([f0])
369
- expect(f0.siblings_before).to be_empty
370
- expect(f0.siblings_after).to eq([f])
371
- expect(f.siblings_after).to be_empty
372
- expect(f0.self_and_siblings).to eq([f0, f])
373
- expect(f.self_and_siblings).to eq([f0, f])
374
- end
375
-
376
- let(:f1) { Label.find_or_create_by_path %w(a1 b1 c1 d1 e1 f1) }
377
-
378
- it "should move a node to another tree" do
379
- f2 = Label.find_or_create_by_path %w(a2 b2 c2 d2 e2 f2)
380
- f1.add_sibling(f2)
381
- expect(f2.ancestry_path).to eq(%w(a1 b1 c1 d1 e1 f2))
382
- expect(f1.parent.reload.children).to eq([f1, f2])
383
- end
384
-
385
- it "should reorder old-parent siblings when a node moves to another tree" do
386
- f2 = Label.find_or_create_by_path %w(a2 b2 c2 d2 e2 f2)
387
- f3 = f2.prepend_sibling(Label.new(:name => "f3"))
388
- f4 = f2.append_sibling(Label.new(:name => "f4"))
389
- f1.add_sibling(f2)
390
- expect(f1.self_and_siblings.collect(&:order_value)).to eq([0, 1])
391
- expect(f3.self_and_siblings.collect(&:order_value)).to eq([0, 1])
392
- expect(f1.self_and_siblings.collect(&:name)).to eq(%w(f1 f2))
393
- expect(f3.self_and_siblings.collect(&:name)).to eq(%w(f3 f4))
394
- end
395
- end
396
-
397
- context "order_value must be set" do
398
-
399
- before do
400
- @root = Label.create(name: 'root')
401
- @a, @b, @c = %w(a b c).map { |n| @root.children.create(name: n) }
402
- end
403
-
404
- it 'should set order_value on roots' do
405
- expect(@root.order_value).to eq(0)
406
- end
407
-
408
- it 'should set order_value with siblings' do
409
- expect(@a.order_value).to eq(0)
410
- expect(@b.order_value).to eq(1)
411
- expect(@c.order_value).to eq(2)
412
- end
413
-
414
- it 'should reset order_value when a node is moved to another location' do
415
- root2 = Label.create(name: 'root2')
416
- root2.add_child @b
417
- expect(@a.order_value).to eq(0)
418
- expect(@b.order_value).to eq(0)
419
- expect(@c.reload.order_value).to eq(1)
420
- end
421
- end
422
-
423
- context "destructive reordering" do
424
- before :each do
425
- # to make sure order_value isn't affected by additional nodes:
426
- create_preorder_tree
427
- @root = Label.create(:name => 'root')
428
- @a = @root.children.create!(:name => 'a')
429
- @b = @a.append_sibling(Label.new(:name => 'b'))
430
- @c = @b.append_sibling(Label.new(:name => 'c'))
431
- end
432
- context "doesn't create sort order gaps" do
433
- it 'from head' do
434
- @a.destroy
435
- expect(@root.reload.children).to eq([@b, @c])
436
- expect(@root.children.map { |ea| ea.order_value }).to eq([0, 1])
437
- end
438
- it 'from mid' do
439
- @b.destroy
440
- expect(@root.reload.children).to eq([@a, @c])
441
- expect(@root.children.map { |ea| ea.order_value }).to eq([0, 1])
442
- end
443
- it 'from tail' do
444
- @c.destroy
445
- expect(@root.reload.children).to eq([@a, @b])
446
- expect(@root.children.map { |ea| ea.order_value }).to eq([0, 1])
447
- end
448
- end
449
-
450
- context 'add_sibling moves descendant nodes' do
451
- let(:roots) { (0..10).map { |ea| Label.create(name: ea) } }
452
- let(:first_root) { roots.first }
453
- let(:last_root) { roots.last }
454
- it 'should retain sort orders of descendants when moving to a new parent' do
455
- expected_order = ('a'..'z').to_a.shuffle
456
- expected_order.map { |ea| first_root.add_child(Label.new(name: ea)) }
457
- actual_order = first_root.children.reload.pluck(:name)
458
- expect(actual_order).to eq(expected_order)
459
- last_root.append_child(first_root)
460
- expect(last_root.self_and_descendants.pluck(:name)).to eq(%w(10 0) + expected_order)
461
- end
462
-
463
- it 'should retain sort orders of descendants when moving within the same new parent' do
464
- path = ('a'..'z').to_a
465
- z = first_root.find_or_create_by_path(path)
466
- z_children_names = (100..150).to_a.shuffle.map { |ea| ea.to_s }
467
- z_children_names.reverse.each { |ea| z.prepend_child(Label.new(name: ea)) }
468
- expect(z.children.reload.pluck(:name)).to eq(z_children_names)
469
- a = first_root.find_by_path(['a'])
470
- # move b up to a's level:
471
- b = a.children.first
472
- a.add_sibling(b)
473
- expect(b.parent).to eq(first_root)
474
- expect(z.children.reload.pluck(:name)).to eq(z_children_names)
475
- end
476
- end
477
-
478
- it "shouldn't fail if all children are destroyed" do
479
- roots = Label.roots.to_a
480
- roots.each { |ea| ea.children.destroy_all }
481
- expect(Label.all.to_a).to match_array(roots)
482
- end
483
- end
484
-
485
- context 'descendent destruction' do
486
- it 'properly destroys descendents created with add_child' do
487
- a = Label.create(name: 'a')
488
- b = Label.new(name: 'b')
489
- a.add_child b
490
- c = Label.new(name: 'c')
491
- b.add_child c
492
- a.destroy
493
- expect(Label.exists?(id: [a.id, b.id, c.id])).to be_falsey
494
- end
495
-
496
- it 'properly destroys descendents created with <<' do
497
- a = Label.create(name: 'a')
498
- b = Label.new(name: 'b')
499
- a.children << b
500
- c = Label.new(name: 'c')
501
- b.children << c
502
- a.destroy
503
- expect(Label.exists?(id: [a.id, b.id, c.id])).to be_falsey
504
- end
505
- end
506
-
507
- context 'preorder' do
508
- it 'returns descendants in proper order' do
509
- create_preorder_tree
510
- a = Label.root
511
- expect(a.name).to eq('a')
512
- expected = ('a'..'r').to_a
513
- expect(a.self_and_descendants_preordered.collect { |ea| ea.name }).to eq(expected)
514
- expect(Label.roots_and_descendants_preordered.collect { |ea| ea.name }).to eq(expected)
515
- # Let's create the second root by hand so we can explicitly set the sort order
516
- Label.create! do |l|
517
- l.name = "a1"
518
- l.order_value = a.order_value + 1
519
- end
520
- create_preorder_tree('1')
521
- # Should be no change:
522
- expect(a.reload.self_and_descendants_preordered.collect { |ea| ea.name }).to eq(expected)
523
- expected += ('a'..'r').collect { |ea| "#{ea}1" }
524
- expect(Label.roots_and_descendants_preordered.collect { |ea| ea.name }).to eq(expected)
525
- end
526
- end unless sqlite? # sqlite doesn't have a power function.
527
-
528
- context 'hash_tree' do
529
- before do
530
- @a = EventLabel.create(name: 'a')
531
- @b = DateLabel.create(name: 'b')
532
- @c = DirectoryLabel.create(name: 'c')
533
- (1..3).each { |i| DirectoryLabel.create!(name: "c#{ i }", mother_id: @c.id) }
534
- end
535
- it 'should return tree with correct scope when called on class' do
536
- tree = DirectoryLabel.hash_tree
537
- expect(tree.keys.size).to eq(1)
538
- expect(tree.keys.first).to eq(@c)
539
- expect(tree[@c].keys.size).to eq(3)
540
- end
541
- it 'should return tree with correct scope when called on all' do
542
- tree = DirectoryLabel.all.hash_tree
543
- expect(tree.keys.size).to eq(1)
544
- expect(tree.keys.first).to eq(@c)
545
- expect(tree[@c].keys.size).to eq(3)
546
- end
547
- it 'should return tree with correct scope when called on scope chain' do
548
- tree = Label.where(name: 'b').hash_tree
549
- expect(tree.keys.size).to eq(1)
550
- expect(tree.keys.first).to eq(@b)
551
- expect(tree[@b]).to eq({})
552
- end
553
- end
554
- end
data/spec/matcher_spec.rb DELETED
@@ -1,34 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'ClosureTree::Test::Matcher' do
4
-
5
- describe 'be_a_closure_tree' do
6
- it { expect(UUIDTag).to be_a_closure_tree }
7
- it { expect(User).to be_a_closure_tree }
8
- it { expect(Label).to be_a_closure_tree.ordered }
9
- it { expect(Metal).to be_a_closure_tree.ordered(:sort_order) }
10
- it { expect(MenuItem).to be_a_closure_tree }
11
- it { expect(Contract).not_to be_a_closure_tree }
12
- end
13
-
14
- describe 'ordered' do
15
- it { expect(Label).to be_a_closure_tree.ordered }
16
- it { expect(UUIDTag).to be_a_closure_tree.ordered }
17
- it { expect(Metal).to be_a_closure_tree.ordered(:sort_order) }
18
- end
19
-
20
- describe 'advisory_lock' do
21
- it 'should use advisory lock' do
22
- expect(User).to be_a_closure_tree.with_advisory_lock
23
- expect(Label).to be_a_closure_tree.ordered.with_advisory_lock
24
- expect(Metal).to be_a_closure_tree.ordered(:sort_order).with_advisory_lock
25
- end
26
-
27
- describe MenuItem do
28
- it 'should not use advisory lock' do
29
- is_expected.to be_a_closure_tree.without_advisory_lock
30
- end
31
- end
32
- end
33
-
34
- end
data/spec/metal_spec.rb DELETED
@@ -1,55 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Metal do
4
- describe '#find_or_create_by_path' do
5
- def assert_correctness(grandchild)
6
- expect(grandchild).to be_a(Metal)
7
- expect(grandchild.description).to eq('slag')
8
- child = grandchild.parent
9
- expect(child).to be_a(Unobtanium)
10
- expect(child.description).to eq('frames')
11
- expect(child.value).to eq('child')
12
- parent = child.parent
13
- expect(parent).to be_a(Adamantium)
14
- expect(parent.description).to eq('claws')
15
- expect(parent.value).to eq('parent')
16
- end
17
-
18
- let(:attr_path) do
19
- [
20
- {value: 'parent', description: 'claws', metal_type: 'Adamantium'},
21
- {value: 'child', description: 'frames', metal_type: 'Unobtanium'},
22
- {value: 'grandchild', description: 'slag', metal_type: 'Metal'}
23
- ]
24
- end
25
-
26
- before do
27
- # ensure the correct root is used in find_or_create_by_path:
28
- [Metal, Adamantium, Unobtanium].each do |metal|
29
- metal.find_or_create_by_path(%w(parent child grandchild))
30
- end
31
- end if false
32
-
33
- it 'creates children from the proper root' do
34
- assert_correctness(Metal.find_or_create_by_path(attr_path))
35
- end
36
-
37
- it 'supports STI from the base class' do
38
- assert_correctness(Metal.find_or_create_by_path(attr_path))
39
- end
40
-
41
- it 'supports STI from a subclass' do
42
- parent = Adamantium.create!(value: 'parent', description: 'claws')
43
- assert_correctness(parent.find_or_create_by_path(attr_path.last(2)))
44
- end
45
-
46
- it 'maintains the current STI subclass if attributes are not specified' do
47
- leaf = Unobtanium.find_or_create_by_path(%w(a b c d))
48
- expect(leaf).to be_a(Unobtanium)
49
- expect(leaf.ancestors.map(&:value)).to eq(%w(c b a))
50
- leaf.ancestors.each do |anc|
51
- expect(anc).to be_a(Unobtanium)
52
- end
53
- end
54
- end
55
- end
data/spec/model_spec.rb DELETED
@@ -1,9 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ClosureTree::Model do
4
- describe '#_ct' do
5
- it 'should delegate to the Support instance on the class' do
6
- expect(Tag.new._ct).to eq(Tag._ct)
7
- end
8
- end
9
- end
@@ -1,13 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Namespace::Type do
4
-
5
- context "class injection" do
6
- it "should build hierarchy classname correctly" do
7
- expect(Namespace::Type.hierarchy_class.to_s).to eq("Namespace::TypeHierarchy")
8
- expect(Namespace::Type._ct.hierarchy_class_name).to eq("Namespace::TypeHierarchy")
9
- expect(Namespace::Type._ct.short_hierarchy_class_name).to eq("TypeHierarchy")
10
- end
11
- end
12
-
13
- end