closure_tree 6.5.0 → 7.4.0

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