closure_tree 4.6.2 → 4.6.3
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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -2
- data/CHANGELOG.md +6 -1
- data/closure_tree.gemspec +1 -1
- data/gemfiles/activerecord_3.2.gemfile +1 -1
- data/gemfiles/activerecord_4.0.gemfile +1 -1
- data/gemfiles/activerecord_4.1.gemfile +1 -1
- data/lib/closure_tree/hierarchy_maintenance.rb +1 -1
- data/lib/closure_tree/test/matcher.rb +13 -9
- data/lib/closure_tree/version.rb +1 -1
- data/spec/cuisine_type_spec.rb +6 -6
- data/spec/label_spec.rb +122 -121
- data/spec/matcher_spec.rb +16 -14
- data/spec/metal_spec.rb +1 -1
- data/spec/namespace_type_spec.rb +3 -3
- data/spec/parallel_spec.rb +12 -12
- data/spec/support_spec.rb +2 -2
- data/spec/tag_examples.rb +135 -132
- data/spec/user_spec.rb +46 -46
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: afbd40867cadc58befec5d4aeda0c0f2684906b7
|
4
|
+
data.tar.gz: 27f8b0415ba7f10e84f50918f8fb4a3304d5d3fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1b47e639ab23e6eec46d1ede597da1bfc2c3a1f2a7b82d9024272695f985ebd8704b9230ab44b5507ebb1226bc098ef5386e7e267f15ca50e9d31f5d7605bab
|
7
|
+
data.tar.gz: ab3224ef55cee5cac66106d80aadf8b144abf132ac1a56ce7fb4b45fc37f38ff72060c336a9ee3ca696785529c2ce872d9b4fcfbb63ded55fbd4171cc111d491
|
data/.travis.yml
CHANGED
@@ -12,7 +12,7 @@ gemfile:
|
|
12
12
|
- gemfiles/activerecord_3.2.gemfile
|
13
13
|
- gemfiles/activerecord_4.0.gemfile
|
14
14
|
- gemfiles/activerecord_4.1.gemfile
|
15
|
-
|
15
|
+
- gemfiles/activerecord_edge.gemfile
|
16
16
|
|
17
17
|
env:
|
18
18
|
- DB=sqlite
|
@@ -22,7 +22,6 @@ env:
|
|
22
22
|
script: WITH_ADVISORY_LOCK_PREFIX=$TRAVIS_JOB_ID bundle exec rake --trace all_spec_flavors
|
23
23
|
|
24
24
|
matrix:
|
25
|
-
fast_finish: true
|
26
25
|
allow_failures:
|
27
26
|
- gemfile: gemfiles/activerecord_edge.gemfile
|
28
27
|
- rvm: rbx-2
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
### 4.6.3
|
4
|
+
|
5
|
+
* More goodness from from [Abdelkader Boudih](https://github.com/seuros), including rspec 3 support.
|
6
|
+
|
3
7
|
### 4.6.2
|
4
|
-
|
8
|
+
|
9
|
+
* Pulled in [106](https://github.com/mceachen/closure_tree/pull/106) which fixed a bug introduced
|
5
10
|
in 4.6.0 which broke if the numeric ordering column wasn't named 'sort_order'. Tests have been
|
6
11
|
added. Thanks for the fix, [Fission Xuiptz](https://github.com/fissionxuiptz)!
|
7
12
|
|
data/closure_tree.gemspec
CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |gem|
|
|
21
21
|
|
22
22
|
gem.add_development_dependency 'rake'
|
23
23
|
gem.add_development_dependency 'yard'
|
24
|
-
gem.add_development_dependency 'rspec', '
|
24
|
+
gem.add_development_dependency 'rspec', '>= 3.0'
|
25
25
|
gem.add_development_dependency 'rspec-instafail'
|
26
26
|
gem.add_development_dependency 'rspec-rails' # FIXME: for rspec-rails and rspec fixture support
|
27
27
|
gem.add_development_dependency 'uuidtools'
|
@@ -25,7 +25,7 @@ module ClosureTree
|
|
25
25
|
changes[_ct.parent_column_name] && # don't validate for cycles if we didn't change our parent
|
26
26
|
parent.present? && # don't validate if we're root
|
27
27
|
parent.self_and_ancestors.include?(self) # < this is expensive :\
|
28
|
-
errors.add(_ct.parent_column_sym,
|
28
|
+
errors.add(_ct.parent_column_sym, I18n.t('closure_tree.loop_error', default: 'You cannot add an ancestor as a descendant'))
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -7,39 +7,39 @@ module ClosureTree
|
|
7
7
|
|
8
8
|
class ClosureTree
|
9
9
|
def matches?(subject)
|
10
|
-
@subject = subject
|
10
|
+
@subject = subject.is_a?(Class) ? subject : subject.class
|
11
11
|
# OPTIMIZE
|
12
12
|
if @subject.respond_to?(:_ct)
|
13
13
|
|
14
14
|
unless @subject.column_names.include?(@subject._ct.parent_column_name)
|
15
|
-
@message = "expected #{@subject.
|
15
|
+
@message = "expected #{@subject.name} to respond to #{@subject._ct.parent_column_name}"
|
16
16
|
return false
|
17
17
|
end
|
18
18
|
|
19
19
|
# Checking if hierarchy table exists (common error)
|
20
20
|
unless @subject.hierarchy_class.table_exists?
|
21
|
-
@message = "expected #{@subject.
|
21
|
+
@message = "expected #{@subject.name}'s hierarchy table '#{@subject.hierarchy_class.table_name}' to exist"
|
22
22
|
return false
|
23
23
|
end
|
24
24
|
|
25
25
|
if @ordered
|
26
26
|
unless @subject._ct.options.include?(:order)
|
27
|
-
@message = "expected #{@subject.
|
27
|
+
@message = "expected #{@subject.name} to be an ordered closure tree"
|
28
28
|
return false
|
29
29
|
end
|
30
30
|
unless @subject.column_names.include?(@subject._ct.options[:order].to_s)
|
31
|
-
@message = "expected #{@subject.
|
31
|
+
@message = "expected #{@subject.name} to have #{@subject._ct.options[:order]} as column"
|
32
32
|
return false
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
36
|
if @with_advisory_lock && !@subject._ct.options[:with_advisory_lock]
|
37
|
-
@message = "expected #{@subject.
|
37
|
+
@message = "expected #{@subject.name} to have advisory lock"
|
38
38
|
return false
|
39
39
|
end
|
40
40
|
|
41
41
|
if @without_advisory_lock && @subject._ct.options[:with_advisory_lock]
|
42
|
-
@message = "expected #{@subject.
|
42
|
+
@message = "expected #{@subject.name} to not have advisory lock"
|
43
43
|
return false
|
44
44
|
end
|
45
45
|
|
@@ -65,13 +65,13 @@ module ClosureTree
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def failure_message
|
68
|
-
@message || "expected #{@subject.
|
68
|
+
@message || "expected #{@subject.name} to #{description}"
|
69
69
|
end
|
70
70
|
|
71
71
|
alias_method :failure_message_for_should, :failure_message
|
72
72
|
|
73
73
|
def failure_message_when_negated
|
74
|
-
"expected #{@subject.
|
74
|
+
"expected #{@subject.name} not be a closure tree, but it is."
|
75
75
|
end
|
76
76
|
|
77
77
|
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
@@ -83,3 +83,7 @@ module ClosureTree
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
end
|
86
|
+
|
87
|
+
RSpec.configure do |c|
|
88
|
+
c.include ClosureTree::Test::Matcher, type: :model
|
89
|
+
end
|
data/lib/closure_tree/version.rb
CHANGED
data/spec/cuisine_type_spec.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
def assert_lineage(e, m)
|
4
|
-
m.parent.
|
5
|
-
m.self_and_ancestors.
|
4
|
+
expect(m.parent).to eq(e)
|
5
|
+
expect(m.self_and_ancestors).to eq([m, e])
|
6
6
|
|
7
7
|
# make sure reloading doesn't affect the self_and_ancestors:
|
8
8
|
m.reload
|
9
|
-
m.self_and_ancestors.
|
9
|
+
expect(m.self_and_ancestors).to eq([m, e])
|
10
10
|
end
|
11
11
|
|
12
12
|
describe CuisineType do
|
@@ -25,14 +25,14 @@ describe CuisineType do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
it "sets the table_name of the hierarchy class properly" do
|
28
|
-
CuisineTypeHierarchy.table_name.
|
28
|
+
expect(CuisineTypeHierarchy.table_name).to eq(ActiveRecord::Base.table_name_prefix + "cuisine_type_hierarchies" + ActiveRecord::Base.table_name_suffix)
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'fixes self_and_ancestors properly on reparenting' do
|
32
32
|
a = CuisineType.create! :name => 'a'
|
33
33
|
b = CuisineType.create! :name => 'b'
|
34
|
-
b.self_and_ancestors.to_a.
|
34
|
+
expect(b.self_and_ancestors.to_a).to eq([b])
|
35
35
|
a.children << b
|
36
|
-
b.self_and_ancestors.to_a.
|
36
|
+
expect(b.self_and_ancestors.to_a).to eq([b, a])
|
37
37
|
end
|
38
38
|
end
|
data/spec/label_spec.rb
CHANGED
@@ -49,7 +49,7 @@ describe Label do
|
|
49
49
|
b = c.parent
|
50
50
|
a = c.root
|
51
51
|
a.destroy
|
52
|
-
Label.exists?(id: [a.id, b.id, c.id]).
|
52
|
+
expect(Label.exists?(id: [a.id, b.id, c.id])).to be_falsey
|
53
53
|
end
|
54
54
|
|
55
55
|
it "properly destroys descendents created with add_child" do
|
@@ -59,9 +59,9 @@ describe Label do
|
|
59
59
|
c = Label.new(name: 'c')
|
60
60
|
b.add_child c
|
61
61
|
a.destroy
|
62
|
-
Label.exists?(a).
|
63
|
-
Label.exists?(b).
|
64
|
-
Label.exists?(c).
|
62
|
+
expect(Label.exists?(a)).to be_falsey
|
63
|
+
expect(Label.exists?(b)).to be_falsey
|
64
|
+
expect(Label.exists?(c)).to be_falsey
|
65
65
|
end
|
66
66
|
|
67
67
|
it "properly destroys descendents created with <<" do
|
@@ -71,9 +71,9 @@ describe Label do
|
|
71
71
|
c = Label.new(name: 'c')
|
72
72
|
b.children << c
|
73
73
|
a.destroy
|
74
|
-
Label.exists?(a).
|
75
|
-
Label.exists?(b).
|
76
|
-
Label.exists?(c).
|
74
|
+
expect(Label.exists?(a)).to be_falsey
|
75
|
+
expect(Label.exists?(b)).to be_falsey
|
76
|
+
expect(Label.exists?(c)).to be_falsey
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
@@ -86,7 +86,7 @@ describe Label do
|
|
86
86
|
l.order_value = ea
|
87
87
|
end
|
88
88
|
end
|
89
|
-
Label.roots.collect { |ea| ea.order_value }.
|
89
|
+
expect(Label.roots.collect { |ea| ea.order_value }).to eq(expected)
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
@@ -94,9 +94,9 @@ describe Label do
|
|
94
94
|
it "should find or create by path" do
|
95
95
|
# class method:
|
96
96
|
c = Label.find_or_create_by_path(%w{grandparent parent child})
|
97
|
-
c.ancestry_path.
|
98
|
-
c.name.
|
99
|
-
c.parent.name.
|
97
|
+
expect(c.ancestry_path).to eq(%w{grandparent parent child})
|
98
|
+
expect(c.name).to eq("child")
|
99
|
+
expect(c.parent.name).to eq("parent")
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
@@ -104,33 +104,33 @@ describe Label do
|
|
104
104
|
it "should associate both sides of the parent and child relationships" do
|
105
105
|
parent = Label.new(:name => 'parent')
|
106
106
|
child = parent.children.build(:name => 'child')
|
107
|
-
parent.
|
108
|
-
parent.
|
109
|
-
child.
|
110
|
-
child.
|
107
|
+
expect(parent).to be_root
|
108
|
+
expect(parent).not_to be_leaf
|
109
|
+
expect(child).not_to be_root
|
110
|
+
expect(child).to be_leaf
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
114
114
|
context "DateLabel" do
|
115
115
|
it "should find or create by path" do
|
116
116
|
date = DateLabel.find_or_create_by_path(%w{2011 November 23})
|
117
|
-
date.ancestry_path.
|
118
|
-
date.self_and_ancestors.each { |ea| ea.class.
|
119
|
-
date.name.
|
120
|
-
date.parent.name.
|
117
|
+
expect(date.ancestry_path).to eq(%w{2011 November 23})
|
118
|
+
date.self_and_ancestors.each { |ea| expect(ea.class).to eq(DateLabel) }
|
119
|
+
expect(date.name).to eq("23")
|
120
|
+
expect(date.parent.name).to eq("November")
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
124
124
|
context "DirectoryLabel" do
|
125
125
|
it "should find or create by path" do
|
126
126
|
dir = DirectoryLabel.find_or_create_by_path(%w{grandparent parent child})
|
127
|
-
dir.ancestry_path.
|
128
|
-
dir.name.
|
129
|
-
dir.parent.name.
|
130
|
-
dir.parent.parent.name.
|
131
|
-
dir.root.name.
|
132
|
-
dir.id.
|
133
|
-
dir.self_and_ancestors.each { |ea| ea.class.
|
127
|
+
expect(dir.ancestry_path).to eq(%w{grandparent parent child})
|
128
|
+
expect(dir.name).to eq("child")
|
129
|
+
expect(dir.parent.name).to eq("parent")
|
130
|
+
expect(dir.parent.parent.name).to eq("grandparent")
|
131
|
+
expect(dir.root.name).to eq("grandparent")
|
132
|
+
expect(dir.id).not_to eq(Label.find_or_create_by_path(%w{grandparent parent child}))
|
133
|
+
dir.self_and_ancestors.each { |ea| expect(ea.class).to eq(DirectoryLabel) }
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
@@ -143,20 +143,21 @@ describe Label do
|
|
143
143
|
end
|
144
144
|
end
|
145
145
|
it "finds roots with specific classes" do
|
146
|
-
Label.roots.
|
147
|
-
DirectoryLabel.roots.
|
148
|
-
EventLabel.roots.
|
146
|
+
expect(Label.roots).to eq(Label.where(:name => 'a').to_a)
|
147
|
+
expect(DirectoryLabel.roots).to be_empty
|
148
|
+
expect(EventLabel.roots).to be_empty
|
149
149
|
end
|
150
150
|
|
151
151
|
it "all is limited to subclasses" do
|
152
|
-
DateLabel.all.map(&:name).
|
153
|
-
DirectoryLabel.all.map(&:name).
|
154
|
-
EventLabel.all.map(&:name).
|
152
|
+
expect(DateLabel.all.map(&:name)).to match_array(%w(f h l n p))
|
153
|
+
expect(DirectoryLabel.all.map(&:name)).to match_array(%w(g q))
|
154
|
+
expect(EventLabel.all.map(&:name)).to eq(%w(r))
|
155
155
|
end
|
156
156
|
|
157
157
|
it "returns descendents regardless of subclass" do
|
158
|
-
Label.root.descendants.map { |ea| ea.class.to_s }.uniq.
|
158
|
+
expect(Label.root.descendants.map { |ea| ea.class.to_s }.uniq).to match_array(
|
159
159
|
%w(Label DateLabel DirectoryLabel EventLabel)
|
160
|
+
)
|
160
161
|
end
|
161
162
|
end
|
162
163
|
|
@@ -167,13 +168,13 @@ describe Label do
|
|
167
168
|
c = Label.new(:name => "c")
|
168
169
|
b.add_child(c)
|
169
170
|
|
170
|
-
a.self_and_descendants.collect do |ea|
|
171
|
+
expect(a.self_and_descendants.collect do |ea|
|
171
172
|
ea.class
|
172
|
-
end.
|
173
|
+
end).to eq([EventLabel, DateLabel, Label])
|
173
174
|
|
174
|
-
a.self_and_descendants.collect do |ea|
|
175
|
+
expect(a.self_and_descendants.collect do |ea|
|
175
176
|
ea.name
|
176
|
-
end.
|
177
|
+
end).to eq(%w(a b c))
|
177
178
|
end
|
178
179
|
end
|
179
180
|
|
@@ -183,37 +184,37 @@ describe Label do
|
|
183
184
|
end
|
184
185
|
|
185
186
|
it "finds roots from the class method" do
|
186
|
-
Label.find_all_by_generation(0).to_a.
|
187
|
+
expect(Label.find_all_by_generation(0).to_a).to eq([@a1, @a2])
|
187
188
|
end
|
188
189
|
|
189
190
|
it "finds roots from themselves" do
|
190
|
-
@a1.find_all_by_generation(0).to_a.
|
191
|
+
expect(@a1.find_all_by_generation(0).to_a).to eq([@a1])
|
191
192
|
end
|
192
193
|
|
193
194
|
it "finds itself for non-roots" do
|
194
|
-
@b1.find_all_by_generation(0).to_a.
|
195
|
+
expect(@b1.find_all_by_generation(0).to_a).to eq([@b1])
|
195
196
|
end
|
196
197
|
|
197
198
|
it "finds children for roots" do
|
198
|
-
Label.find_all_by_generation(1).to_a.
|
199
|
+
expect(Label.find_all_by_generation(1).to_a).to eq([@b1, @b2])
|
199
200
|
end
|
200
201
|
|
201
202
|
it "finds children" do
|
202
|
-
@a1.find_all_by_generation(1).to_a.
|
203
|
-
@b1.find_all_by_generation(1).to_a.
|
203
|
+
expect(@a1.find_all_by_generation(1).to_a).to eq([@b1])
|
204
|
+
expect(@b1.find_all_by_generation(1).to_a).to eq([@c1, @c2])
|
204
205
|
end
|
205
206
|
|
206
207
|
it "finds grandchildren for roots" do
|
207
|
-
Label.find_all_by_generation(2).to_a.
|
208
|
+
expect(Label.find_all_by_generation(2).to_a).to eq([@c1, @c2, @c3])
|
208
209
|
end
|
209
210
|
|
210
211
|
it "finds grandchildren" do
|
211
|
-
@a1.find_all_by_generation(2).to_a.
|
212
|
-
@b1.find_all_by_generation(2).to_a.
|
212
|
+
expect(@a1.find_all_by_generation(2).to_a).to eq([@c1, @c2])
|
213
|
+
expect(@b1.find_all_by_generation(2).to_a).to eq([@d1, @d2])
|
213
214
|
end
|
214
215
|
|
215
216
|
it "finds great-grandchildren for roots" do
|
216
|
-
Label.find_all_by_generation(3).to_a.
|
217
|
+
expect(Label.find_all_by_generation(3).to_a).to eq([@d1, @d2, @d3])
|
217
218
|
end
|
218
219
|
end
|
219
220
|
|
@@ -223,17 +224,17 @@ describe Label do
|
|
223
224
|
end
|
224
225
|
|
225
226
|
it "self_and_descendants should result in one select" do
|
226
|
-
count_queries do
|
227
|
+
expect(count_queries do
|
227
228
|
a1_array = @a1.self_and_descendants
|
228
|
-
a1_array.collect { |ea| ea.name }.
|
229
|
-
end.
|
229
|
+
expect(a1_array.collect { |ea| ea.name }).to eq(%w(a1 b1 c1 c2 d1 d2))
|
230
|
+
end).to eq(1)
|
230
231
|
end
|
231
232
|
|
232
233
|
it "self_and_ancestors should result in one select" do
|
233
|
-
count_queries do
|
234
|
+
expect(count_queries do
|
234
235
|
d1_array = @d1.self_and_ancestors
|
235
|
-
d1_array.collect { |ea| ea.name }.
|
236
|
-
end.
|
236
|
+
expect(d1_array.collect { |ea| ea.name }).to eq(%w(d1 c1 b1 a1))
|
237
|
+
end).to eq(1)
|
237
238
|
end
|
238
239
|
end
|
239
240
|
|
@@ -262,32 +263,32 @@ describe Label do
|
|
262
263
|
end
|
263
264
|
|
264
265
|
it 'order_values properly' do
|
265
|
-
children_name_and_order.
|
266
|
+
expect(children_name_and_order).to eq([['a', 0], ['b', 1], ['c', 2], ['d', 3]])
|
266
267
|
end
|
267
268
|
|
268
269
|
it 'when inserted before' do
|
269
270
|
@b.append_sibling(@a)
|
270
|
-
children_name_and_order.
|
271
|
+
expect(children_name_and_order).to eq([['b', 0], ['a', 1], ['c', 2], ['d', 3]])
|
271
272
|
end
|
272
273
|
|
273
274
|
it 'when inserted after' do
|
274
275
|
@a.append_sibling(@c)
|
275
|
-
children_name_and_order.
|
276
|
+
expect(children_name_and_order).to eq([['a', 0], ['c', 1], ['b', 2], ['d', 3]])
|
276
277
|
end
|
277
278
|
|
278
279
|
it 'when inserted before the first' do
|
279
280
|
@a.prepend_sibling(@d)
|
280
|
-
children_name_and_order.
|
281
|
+
expect(children_name_and_order).to eq([['d', 0], ['a', 1], ['b', 2], ['c', 3]])
|
281
282
|
end
|
282
283
|
|
283
284
|
it 'when inserted after the last' do
|
284
285
|
@d.append_sibling(@b)
|
285
|
-
children_name_and_order.
|
286
|
+
expect(children_name_and_order).to eq([['a', 0], ['c', 1], ['d', 2], ['b', 3]])
|
286
287
|
end
|
287
288
|
|
288
289
|
it 'prepends to root nodes' do
|
289
290
|
@parent.prepend_sibling(@f)
|
290
|
-
roots_name_and_order.
|
291
|
+
expect(roots_name_and_order).to eq([['f', 0], ['parent', 1], ['e', 2]])
|
291
292
|
end
|
292
293
|
end
|
293
294
|
|
@@ -298,29 +299,29 @@ describe Label do
|
|
298
299
|
c = Label.create(name: 'c')
|
299
300
|
|
300
301
|
a.append_sibling(b)
|
301
|
-
a.self_and_siblings.collect(&:name).
|
302
|
-
root.reload.children.collect(&:name).
|
303
|
-
root.children.collect(&:order_value).
|
302
|
+
expect(a.self_and_siblings.collect(&:name)).to eq(%w(a b))
|
303
|
+
expect(root.reload.children.collect(&:name)).to eq(%w(a b))
|
304
|
+
expect(root.children.collect(&:order_value)).to eq([0, 1])
|
304
305
|
|
305
306
|
a.prepend_sibling(b)
|
306
|
-
a.self_and_siblings.collect(&:name).
|
307
|
-
root.reload.children.collect(&:name).
|
308
|
-
root.children.collect(&:order_value).
|
307
|
+
expect(a.self_and_siblings.collect(&:name)).to eq(%w(b a))
|
308
|
+
expect(root.reload.children.collect(&:name)).to eq(%w(b a))
|
309
|
+
expect(root.children.collect(&:order_value)).to eq([0, 1])
|
309
310
|
|
310
311
|
a.append_sibling(c)
|
311
|
-
a.self_and_siblings.collect(&:name).
|
312
|
-
root.reload.children.collect(&:name).
|
313
|
-
root.children.collect(&:order_value).
|
312
|
+
expect(a.self_and_siblings.collect(&:name)).to eq(%w(b a c))
|
313
|
+
expect(root.reload.children.collect(&:name)).to eq(%w(b a c))
|
314
|
+
expect(root.children.collect(&:order_value)).to eq([0, 1, 2])
|
314
315
|
|
315
316
|
# We need to reload b because it was updated by a.append_sibling(c)
|
316
317
|
b.reload.append_sibling(c)
|
317
|
-
root.reload.children.collect(&:name).
|
318
|
-
root.children.collect(&:order_value).
|
318
|
+
expect(root.reload.children.collect(&:name)).to eq(%w(b c a))
|
319
|
+
expect(root.children.collect(&:order_value)).to eq([0, 1, 2])
|
319
320
|
|
320
321
|
# We need to reload a because it was updated by b.append_sibling(c)
|
321
322
|
d = a.reload.append_sibling(Label.new(:name => "d"))
|
322
|
-
d.self_and_siblings.collect(&:name).
|
323
|
-
d.self_and_siblings.collect(&:order_value).
|
323
|
+
expect(d.self_and_siblings.collect(&:name)).to eq(%w(b c a d))
|
324
|
+
expect(d.self_and_siblings.collect(&:order_value)).to eq([0, 1, 2, 3])
|
324
325
|
end
|
325
326
|
|
326
327
|
# https://github.com/mceachen/closure_tree/issues/84
|
@@ -328,36 +329,36 @@ describe Label do
|
|
328
329
|
root = Label.create(:name => "root")
|
329
330
|
a = Label.create(:name => "a", :parent => root)
|
330
331
|
b = Label.create(:name => "b", :parent => root)
|
331
|
-
a.order_value.
|
332
|
-
b.order_value.
|
332
|
+
expect(a.order_value).to eq(0)
|
333
|
+
expect(b.order_value).to eq(1)
|
333
334
|
#c = Label.create(:name => "c")
|
334
335
|
|
335
336
|
# should the order_value for roots be set?
|
336
|
-
root.order_value.
|
337
|
-
root.order_value.
|
337
|
+
expect(root.order_value).not_to be_nil
|
338
|
+
expect(root.order_value).to eq(0)
|
338
339
|
|
339
340
|
# order_value should never be nil on a child.
|
340
|
-
a.order_value.
|
341
|
-
a.order_value.
|
341
|
+
expect(a.order_value).not_to be_nil
|
342
|
+
expect(a.order_value).to eq(0)
|
342
343
|
# Add a child to root at end of children.
|
343
344
|
root.children << b
|
344
|
-
b.parent.
|
345
|
-
a.self_and_siblings.collect(&:name).
|
346
|
-
root.reload.children.collect(&:name).
|
347
|
-
root.children.collect(&:order_value).
|
345
|
+
expect(b.parent).to eq(root)
|
346
|
+
expect(a.self_and_siblings.collect(&:name)).to eq(%w(a b))
|
347
|
+
expect(root.reload.children.collect(&:name)).to eq(%w(a b))
|
348
|
+
expect(root.children.collect(&:order_value)).to eq([0, 1])
|
348
349
|
end
|
349
350
|
|
350
351
|
context "#add_sibling" do
|
351
352
|
it "should move a node before another node which has an uninitialized order_value" do
|
352
353
|
f = Label.find_or_create_by_path %w(a b c d e fa)
|
353
354
|
f0 = f.prepend_sibling(Label.new(:name => "fb")) # < not alpha sort, so name shouldn't matter
|
354
|
-
f0.ancestry_path.
|
355
|
-
f.siblings_before.to_a.
|
356
|
-
f0.siblings_before.
|
357
|
-
f0.siblings_after.
|
358
|
-
f.siblings_after.
|
359
|
-
f0.self_and_siblings.
|
360
|
-
f.self_and_siblings.
|
355
|
+
expect(f0.ancestry_path).to eq(%w(a b c d e fb))
|
356
|
+
expect(f.siblings_before.to_a).to eq([f0])
|
357
|
+
expect(f0.siblings_before).to be_empty
|
358
|
+
expect(f0.siblings_after).to eq([f])
|
359
|
+
expect(f.siblings_after).to be_empty
|
360
|
+
expect(f0.self_and_siblings).to eq([f0, f])
|
361
|
+
expect(f.self_and_siblings).to eq([f0, f])
|
361
362
|
end
|
362
363
|
|
363
364
|
let(:f1) { Label.find_or_create_by_path %w(a1 b1 c1 d1 e1 f1) }
|
@@ -365,8 +366,8 @@ describe Label do
|
|
365
366
|
it "should move a node to another tree" do
|
366
367
|
f2 = Label.find_or_create_by_path %w(a2 b2 c2 d2 e2 f2)
|
367
368
|
f1.add_sibling(f2)
|
368
|
-
f2.ancestry_path.
|
369
|
-
f1.parent.reload.children.
|
369
|
+
expect(f2.ancestry_path).to eq(%w(a1 b1 c1 d1 e1 f2))
|
370
|
+
expect(f1.parent.reload.children).to eq([f1, f2])
|
370
371
|
end
|
371
372
|
|
372
373
|
it "should reorder old-parent siblings when a node moves to another tree" do
|
@@ -374,10 +375,10 @@ describe Label do
|
|
374
375
|
f3 = f2.prepend_sibling(Label.new(:name => "f3"))
|
375
376
|
f4 = f2.append_sibling(Label.new(:name => "f4"))
|
376
377
|
f1.add_sibling(f2)
|
377
|
-
f1.self_and_siblings.collect(&:order_value).
|
378
|
-
f3.self_and_siblings.collect(&:order_value).
|
379
|
-
f1.self_and_siblings.collect(&:name).
|
380
|
-
f3.self_and_siblings.collect(&:name).
|
378
|
+
expect(f1.self_and_siblings.collect(&:order_value)).to eq([0, 1])
|
379
|
+
expect(f3.self_and_siblings.collect(&:order_value)).to eq([0, 1])
|
380
|
+
expect(f1.self_and_siblings.collect(&:name)).to eq(%w(f1 f2))
|
381
|
+
expect(f3.self_and_siblings.collect(&:name)).to eq(%w(f3 f4))
|
381
382
|
end
|
382
383
|
end
|
383
384
|
|
@@ -389,21 +390,21 @@ describe Label do
|
|
389
390
|
end
|
390
391
|
|
391
392
|
it 'should set order_value on roots' do
|
392
|
-
@root.order_value.
|
393
|
+
expect(@root.order_value).to eq(0)
|
393
394
|
end
|
394
395
|
|
395
396
|
it 'should set order_value with siblings' do
|
396
|
-
@a.order_value.
|
397
|
-
@b.order_value.
|
398
|
-
@c.order_value.
|
397
|
+
expect(@a.order_value).to eq(0)
|
398
|
+
expect(@b.order_value).to eq(1)
|
399
|
+
expect(@c.order_value).to eq(2)
|
399
400
|
end
|
400
401
|
|
401
402
|
it 'should reset order_value when a node is moved to another location' do
|
402
403
|
root2 = Label.create(name: 'root2')
|
403
404
|
root2.add_child @b
|
404
|
-
@a.order_value.
|
405
|
-
@b.order_value.
|
406
|
-
@c.reload.order_value.
|
405
|
+
expect(@a.order_value).to eq(0)
|
406
|
+
expect(@b.order_value).to eq(0)
|
407
|
+
expect(@c.reload.order_value).to eq(1)
|
407
408
|
end
|
408
409
|
end
|
409
410
|
|
@@ -419,18 +420,18 @@ describe Label do
|
|
419
420
|
context "doesn't create sort order gaps" do
|
420
421
|
it 'from head' do
|
421
422
|
@a.destroy
|
422
|
-
@root.reload.children.
|
423
|
-
@root.children.map { |ea| ea.order_value }.
|
423
|
+
expect(@root.reload.children).to eq([@b, @c])
|
424
|
+
expect(@root.children.map { |ea| ea.order_value }).to eq([0, 1])
|
424
425
|
end
|
425
426
|
it 'from mid' do
|
426
427
|
@b.destroy
|
427
|
-
@root.reload.children.
|
428
|
-
@root.children.map { |ea| ea.order_value }.
|
428
|
+
expect(@root.reload.children).to eq([@a, @c])
|
429
|
+
expect(@root.children.map { |ea| ea.order_value }).to eq([0, 1])
|
429
430
|
end
|
430
431
|
it 'from tail' do
|
431
432
|
@c.destroy
|
432
|
-
@root.reload.children.
|
433
|
-
@root.children.map { |ea| ea.order_value }.
|
433
|
+
expect(@root.reload.children).to eq([@a, @b])
|
434
|
+
expect(@root.children.map { |ea| ea.order_value }).to eq([0, 1])
|
434
435
|
end
|
435
436
|
end
|
436
437
|
|
@@ -442,9 +443,9 @@ describe Label do
|
|
442
443
|
expected_order = ('a'..'z').to_a.shuffle
|
443
444
|
expected_order.map { |ea| first_root.add_child(Label.new(name: ea)) }
|
444
445
|
actual_order = first_root.children(reload = true).pluck(:name)
|
445
|
-
actual_order.
|
446
|
+
expect(actual_order).to eq(expected_order)
|
446
447
|
last_root.append_child(first_root)
|
447
|
-
last_root.self_and_descendants.pluck(:name).
|
448
|
+
expect(last_root.self_and_descendants.pluck(:name)).to eq(%w(10 0) + expected_order)
|
448
449
|
end
|
449
450
|
|
450
451
|
it 'should retain sort orders of descendants when moving within the same new parent' do
|
@@ -452,20 +453,20 @@ describe Label do
|
|
452
453
|
z = first_root.find_or_create_by_path(path)
|
453
454
|
z_children_names = (100..150).to_a.shuffle.map { |ea| ea.to_s }
|
454
455
|
z_children_names.reverse.each { |ea| z.prepend_child(Label.new(name: ea)) }
|
455
|
-
z.children(reload = true).pluck(:name).
|
456
|
+
expect(z.children(reload = true).pluck(:name)).to eq(z_children_names)
|
456
457
|
a = first_root.find_by_path(['a'])
|
457
458
|
# move b up to a's level:
|
458
459
|
b = a.children.first
|
459
460
|
a.add_sibling(b)
|
460
|
-
b.parent.
|
461
|
-
z.children(reload = true).pluck(:name).
|
461
|
+
expect(b.parent).to eq(first_root)
|
462
|
+
expect(z.children(reload = true).pluck(:name)).to eq(z_children_names)
|
462
463
|
end
|
463
464
|
end
|
464
465
|
|
465
466
|
it "shouldn't fail if all children are destroyed" do
|
466
467
|
roots = Label.roots.to_a
|
467
468
|
roots.each { |ea| ea.children.destroy_all }
|
468
|
-
Label.all.to_a.
|
469
|
+
expect(Label.all.to_a).to match_array(roots)
|
469
470
|
end
|
470
471
|
end
|
471
472
|
|
@@ -477,7 +478,7 @@ describe Label do
|
|
477
478
|
c = Label.new(name: 'c')
|
478
479
|
b.add_child c
|
479
480
|
a.destroy
|
480
|
-
Label.exists?(id: [a.id, b.id, c.id]).
|
481
|
+
expect(Label.exists?(id: [a.id, b.id, c.id])).to be_falsey
|
481
482
|
end
|
482
483
|
|
483
484
|
it 'properly destroys descendents created with <<' do
|
@@ -487,7 +488,7 @@ describe Label do
|
|
487
488
|
c = Label.new(name: 'c')
|
488
489
|
b.children << c
|
489
490
|
a.destroy
|
490
|
-
Label.exists?(id: [a.id, b.id, c.id]).
|
491
|
+
expect(Label.exists?(id: [a.id, b.id, c.id])).to be_falsey
|
491
492
|
end
|
492
493
|
end
|
493
494
|
|
@@ -495,10 +496,10 @@ describe Label do
|
|
495
496
|
it 'returns descendants in proper order' do
|
496
497
|
create_preorder_tree
|
497
498
|
a = Label.root
|
498
|
-
a.name.
|
499
|
+
expect(a.name).to eq('a')
|
499
500
|
expected = ('a'..'r').to_a
|
500
|
-
a.self_and_descendants_preordered.collect { |ea| ea.name }.
|
501
|
-
Label.roots_and_descendants_preordered.collect { |ea| ea.name }.
|
501
|
+
expect(a.self_and_descendants_preordered.collect { |ea| ea.name }).to eq(expected)
|
502
|
+
expect(Label.roots_and_descendants_preordered.collect { |ea| ea.name }).to eq(expected)
|
502
503
|
# Let's create the second root by hand so we can explicitly set the sort order
|
503
504
|
Label.create! do |l|
|
504
505
|
l.name = "a1"
|
@@ -506,9 +507,9 @@ describe Label do
|
|
506
507
|
end
|
507
508
|
create_preorder_tree('1')
|
508
509
|
# Should be no change:
|
509
|
-
a.reload.self_and_descendants_preordered.collect { |ea| ea.name }.
|
510
|
+
expect(a.reload.self_and_descendants_preordered.collect { |ea| ea.name }).to eq(expected)
|
510
511
|
expected += ('a'..'r').collect { |ea| "#{ea}1" }
|
511
|
-
Label.roots_and_descendants_preordered.collect { |ea| ea.name }.
|
512
|
+
expect(Label.roots_and_descendants_preordered.collect { |ea| ea.name }).to eq(expected)
|
512
513
|
end
|
513
514
|
end unless ENV['DB'] == 'sqlite' # sqlite doesn't have a power function.
|
514
515
|
end
|