mongoid_orderable 6.0.4 → 6.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -3
- data/lib/mongoid/orderable/configs/field_config.rb +1 -1
- data/lib/mongoid/orderable/generators/base.rb +1 -1
- data/lib/mongoid/orderable/generators/listable.rb +1 -1
- data/lib/mongoid/orderable/generators/lock_collection.rb +1 -1
- data/lib/mongoid/orderable/generators/movable.rb +1 -1
- data/lib/mongoid/orderable/generators/position.rb +3 -3
- data/lib/mongoid/orderable/generators/scope.rb +1 -1
- data/lib/mongoid/orderable/handlers/base.rb +32 -6
- data/lib/mongoid/orderable/handlers/document.rb +9 -1
- data/lib/mongoid/orderable/handlers/document_transactional.rb +3 -6
- data/lib/mongoid/orderable/handlers/transaction.rb +6 -2
- data/lib/mongoid/orderable/installer.rb +1 -1
- data/lib/mongoid/orderable/mixins/callbacks.rb +3 -1
- data/lib/mongoid/orderable/mixins/movable.rb +7 -3
- data/lib/mongoid/orderable/version.rb +1 -1
- data/lib/mongoid_orderable.rb +1 -2
- metadata +5 -92
- data/spec/integration/cascadeable_spec.rb +0 -12
- data/spec/integration/concurrency_spec.rb +0 -232
- data/spec/integration/conditional_spec.rb +0 -36
- data/spec/integration/customized_spec.rb +0 -31
- data/spec/integration/embedded_spec.rb +0 -63
- data/spec/integration/foreign_key_spec.rb +0 -33
- data/spec/integration/inherited_spec.rb +0 -54
- data/spec/integration/multiple_fields_spec.rb +0 -554
- data/spec/integration/multiple_scoped_spec.rb +0 -63
- data/spec/integration/no_indexed_spec.rb +0 -23
- data/spec/integration/scoped_spec.rb +0 -151
- data/spec/integration/simple_spec.rb +0 -184
- data/spec/integration/string_scoped_spec.rb +0 -28
- data/spec/integration/zero_based_spec.rb +0 -161
- data/spec/spec_helper.rb +0 -42
- data/spec/support/models.rb +0 -134
@@ -1,151 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ScopedOrderable do
|
4
|
-
|
5
|
-
shared_examples_for 'scoped_orderable' do
|
6
|
-
|
7
|
-
def positions
|
8
|
-
ScopedOrderable.order_by([:group_id, :asc], [:position, :asc]).map(&:position)
|
9
|
-
end
|
10
|
-
|
11
|
-
before :each do
|
12
|
-
2.times { ScopedOrderable.create! group_id: 1 }
|
13
|
-
3.times { ScopedOrderable.create! group_id: 2 }
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'should set proper position while creation' do
|
17
|
-
expect(positions).to eq([1, 2, 1, 2, 3])
|
18
|
-
end
|
19
|
-
|
20
|
-
describe 'removement' do
|
21
|
-
it 'top' do
|
22
|
-
ScopedOrderable.where(position: 1, group_id: 1).destroy
|
23
|
-
expect(positions).to eq([1, 1, 2, 3])
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'bottom' do
|
27
|
-
ScopedOrderable.where(position: 3, group_id: 2).destroy
|
28
|
-
expect(positions).to eq([1, 2, 1, 2])
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'middle' do
|
32
|
-
ScopedOrderable.where(position: 2, group_id: 2).destroy
|
33
|
-
expect(positions).to eq([1, 2, 1, 2])
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe 'inserting' do
|
38
|
-
it 'top' do
|
39
|
-
newbie = ScopedOrderable.create! move_to: :top, group_id: 1
|
40
|
-
expect(positions).to eq([1, 2, 3, 1, 2, 3])
|
41
|
-
expect(newbie.position).to eq(1)
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'bottom' do
|
45
|
-
newbie = ScopedOrderable.create! move_to: :bottom, group_id: 2
|
46
|
-
expect(positions).to eq([1, 2, 1, 2, 3, 4])
|
47
|
-
expect(newbie.position).to eq(4)
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'middle' do
|
51
|
-
newbie = ScopedOrderable.create! move_to: 2, group_id: 2
|
52
|
-
expect(positions).to eq([1, 2, 1, 2, 3, 4])
|
53
|
-
expect(newbie.position).to eq(2)
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'middle (with a numeric string)' do
|
57
|
-
newbie = ScopedOrderable.create! move_to: '2', group_id: 2
|
58
|
-
expect(positions).to eq([1, 2, 1, 2, 3, 4])
|
59
|
-
expect(newbie.position).to eq(2)
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'middle (with a non-numeric string)' do
|
63
|
-
expect do
|
64
|
-
ScopedOrderable.create! move_to: 'two', group_id: 2
|
65
|
-
end.to raise_error Mongoid::Orderable::Errors::InvalidTargetPosition
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
describe 'index' do
|
70
|
-
it 'is not on position alone' do
|
71
|
-
expect(ScopedOrderable.index_specifications.detect { |spec| spec.key == { position: 1 } }).to be_nil
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'is on compound fields' do
|
75
|
-
expect(ScopedOrderable.index_specifications.detect { |spec| spec.key == { group_id: 1, position: 1 } }).to_not be_nil
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
describe 'scope movement' do
|
80
|
-
let(:record) { ScopedOrderable.where(group_id: 2, position: 2).first }
|
81
|
-
|
82
|
-
it 'to a new scope group' do
|
83
|
-
record.update_attributes group_id: 3
|
84
|
-
expect(positions).to eq([1, 2, 1, 2, 1])
|
85
|
-
expect(record.position).to eq(1)
|
86
|
-
end
|
87
|
-
|
88
|
-
context 'when moving to an existing scope group' do
|
89
|
-
it 'without a position' do
|
90
|
-
record.update_attributes group_id: 1
|
91
|
-
expect(positions).to eq([1, 2, 3, 1, 2])
|
92
|
-
expect(record.reload.position).to eq(3)
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'with symbol position' do
|
96
|
-
record.update_attributes group_id: 1, move_to: :top
|
97
|
-
expect(positions).to eq([1, 2, 3, 1, 2])
|
98
|
-
expect(record.reload.position).to eq(1)
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'with point position' do
|
102
|
-
record.update_attributes group_id: 1, move_to: 2
|
103
|
-
expect(positions).to eq([1, 2, 3, 1, 2])
|
104
|
-
expect(record.reload.position).to eq(2)
|
105
|
-
end
|
106
|
-
|
107
|
-
it 'with point position (with a numeric string)' do
|
108
|
-
record.update_attributes group_id: 1, move_to: '2'
|
109
|
-
expect(positions).to eq([1, 2, 3, 1, 2])
|
110
|
-
expect(record.reload.position).to eq(2)
|
111
|
-
end
|
112
|
-
|
113
|
-
it 'with point position (with a non-numeric string)' do
|
114
|
-
expect do
|
115
|
-
record.update_attributes group_id: 1, move_to: 'two'
|
116
|
-
end.to raise_error Mongoid::Orderable::Errors::InvalidTargetPosition
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
describe 'utility methods' do
|
122
|
-
it 'should return a collection of items lower/higher on the list for next_items/previous_items' do
|
123
|
-
record1 = ScopedOrderable.where(group_id: 1, position: 1).first
|
124
|
-
record2 = ScopedOrderable.where(group_id: 1, position: 2).first
|
125
|
-
record3 = ScopedOrderable.where(group_id: 2, position: 1).first
|
126
|
-
record4 = ScopedOrderable.where(group_id: 2, position: 2).first
|
127
|
-
record5 = ScopedOrderable.where(group_id: 2, position: 3).first
|
128
|
-
expect(record1.next_items.to_a).to eq([record2])
|
129
|
-
expect(record5.previous_items.to_a).to eq([record3, record4])
|
130
|
-
expect(record3.previous_items.to_a).to eq([])
|
131
|
-
expect(record3.next_items.to_a).to eq([record4, record5])
|
132
|
-
expect(record1.next_item).to eq(record2)
|
133
|
-
expect(record2.previous_item).to eq(record1)
|
134
|
-
expect(record1.previous_item).to eq(nil)
|
135
|
-
expect(record2.next_item).to eq(nil)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
context 'with transactions' do
|
141
|
-
enable_transactions!
|
142
|
-
|
143
|
-
it_behaves_like 'scoped_orderable'
|
144
|
-
end
|
145
|
-
|
146
|
-
context 'without transactions' do
|
147
|
-
disable_transactions!
|
148
|
-
|
149
|
-
it_behaves_like 'scoped_orderable'
|
150
|
-
end
|
151
|
-
end
|
@@ -1,184 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe SimpleOrderable do
|
4
|
-
|
5
|
-
shared_examples_for 'simple_orderable' do
|
6
|
-
|
7
|
-
def positions
|
8
|
-
SimpleOrderable.pluck(:position).sort
|
9
|
-
end
|
10
|
-
|
11
|
-
before :each do
|
12
|
-
5.times { SimpleOrderable.create! }
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'should have proper position field' do
|
16
|
-
expect(SimpleOrderable.fields.key?('position')).to be true
|
17
|
-
expect(SimpleOrderable.fields['position'].options[:type]).to eq(Integer)
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'should have index on position field' do
|
21
|
-
expect(SimpleOrderable.index_specifications.detect { |spec| spec.key == { position: 1 } }).not_to be_nil
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'should have a orderable base of 1' do
|
25
|
-
expect(SimpleOrderable.create!.orderable_top).to eq(1)
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'should set proper position while creation' do
|
29
|
-
expect(positions).to eq([1, 2, 3, 4, 5])
|
30
|
-
end
|
31
|
-
|
32
|
-
describe 'removement' do
|
33
|
-
it 'top' do
|
34
|
-
SimpleOrderable.where(position: 1).destroy
|
35
|
-
expect(positions).to eq([1, 2, 3, 4])
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'bottom' do
|
39
|
-
SimpleOrderable.where(position: 5).destroy
|
40
|
-
expect(positions).to eq([1, 2, 3, 4])
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'middle' do
|
44
|
-
SimpleOrderable.where(position: 3).destroy
|
45
|
-
expect(positions).to eq([1, 2, 3, 4])
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
describe 'inserting' do
|
50
|
-
it 'top' do
|
51
|
-
newbie = SimpleOrderable.create! move_to: :top
|
52
|
-
expect(positions).to eq([1, 2, 3, 4, 5, 6])
|
53
|
-
expect(newbie.position).to eq(1)
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'bottom' do
|
57
|
-
newbie = SimpleOrderable.create! move_to: :bottom
|
58
|
-
expect(positions).to eq([1, 2, 3, 4, 5, 6])
|
59
|
-
expect(newbie.position).to eq(6)
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'middle' do
|
63
|
-
newbie = SimpleOrderable.create! move_to: 4
|
64
|
-
expect(positions).to eq([1, 2, 3, 4, 5, 6])
|
65
|
-
expect(newbie.position).to eq(4)
|
66
|
-
end
|
67
|
-
|
68
|
-
it 'middle (with a numeric string)' do
|
69
|
-
newbie = SimpleOrderable.create! move_to: '4'
|
70
|
-
expect(positions).to eq([1, 2, 3, 4, 5, 6])
|
71
|
-
expect(newbie.position).to eq(4)
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'middle (with a non-numeric string)' do
|
75
|
-
expect do
|
76
|
-
SimpleOrderable.create! move_to: 'four'
|
77
|
-
end.to raise_error Mongoid::Orderable::Errors::InvalidTargetPosition
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'simultaneous create and update' do
|
81
|
-
newbie = SimpleOrderable.new
|
82
|
-
newbie.send(:orderable_before_update) { }
|
83
|
-
expect(newbie.position).to eq(6)
|
84
|
-
another = SimpleOrderable.create!
|
85
|
-
expect(another.position).to eq(6)
|
86
|
-
newbie.save!
|
87
|
-
expect(positions).to eq([1, 2, 3, 4, 5, 6, 7])
|
88
|
-
expect(newbie.position).to eq(7)
|
89
|
-
expect(another.position).to eq(6)
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'parallel updates' do
|
93
|
-
newbie = SimpleOrderable.new
|
94
|
-
newbie.send(:orderable_before_update) { }
|
95
|
-
another = SimpleOrderable.create!
|
96
|
-
newbie.save!
|
97
|
-
expect(positions).to eq([1, 2, 3, 4, 5, 6, 7])
|
98
|
-
expect(newbie.position).to eq(7)
|
99
|
-
expect(another.position).to eq(6)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
describe 'movement' do
|
104
|
-
it 'higher from top' do
|
105
|
-
record = SimpleOrderable.where(position: 1).first
|
106
|
-
record.update_attributes move_to: :higher
|
107
|
-
expect(positions).to eq([1, 2, 3, 4, 5])
|
108
|
-
expect(record.reload.position).to eq(1)
|
109
|
-
end
|
110
|
-
|
111
|
-
it 'higher from bottom' do
|
112
|
-
record = SimpleOrderable.where(position: 5).first
|
113
|
-
record.update_attributes move_to: :higher
|
114
|
-
expect(positions).to eq([1, 2, 3, 4, 5])
|
115
|
-
expect(record.reload.position).to eq(4)
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'higher from middle' do
|
119
|
-
record = SimpleOrderable.where(position: 3).first
|
120
|
-
record.update_attributes move_to: :higher
|
121
|
-
expect(positions).to eq([1, 2, 3, 4, 5])
|
122
|
-
expect(record.reload.position).to eq(2)
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'lower from top' do
|
126
|
-
record = SimpleOrderable.where(position: 1).first
|
127
|
-
record.update_attributes move_to: :lower
|
128
|
-
expect(positions).to eq([1, 2, 3, 4, 5])
|
129
|
-
expect(record.reload.position).to eq(2)
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'lower from bottom' do
|
133
|
-
record = SimpleOrderable.where(position: 5).first
|
134
|
-
record.update_attributes move_to: :lower
|
135
|
-
expect(positions).to eq([1, 2, 3, 4, 5])
|
136
|
-
expect(record.reload.position).to eq(5)
|
137
|
-
end
|
138
|
-
|
139
|
-
it 'lower from middle' do
|
140
|
-
record = SimpleOrderable.where(position: 3).first
|
141
|
-
record.update_attributes move_to: :lower
|
142
|
-
expect(positions).to eq([1, 2, 3, 4, 5])
|
143
|
-
expect(record.reload.position).to eq(4)
|
144
|
-
end
|
145
|
-
|
146
|
-
it 'does nothing if position not change' do
|
147
|
-
record = SimpleOrderable.where(position: 3).first
|
148
|
-
record.save
|
149
|
-
expect(positions).to eq([1, 2, 3, 4, 5])
|
150
|
-
expect(record.reload.position).to eq(3)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
describe 'utility methods' do
|
155
|
-
it 'should return a collection of items lower/higher on the list for next_items/previous_items' do
|
156
|
-
record1 = SimpleOrderable.where(position: 1).first
|
157
|
-
record2 = SimpleOrderable.where(position: 2).first
|
158
|
-
record3 = SimpleOrderable.where(position: 3).first
|
159
|
-
record4 = SimpleOrderable.where(position: 4).first
|
160
|
-
record5 = SimpleOrderable.where(position: 5).first
|
161
|
-
expect(record1.next_items.to_a).to eq([record2, record3, record4, record5])
|
162
|
-
expect(record5.previous_items.to_a).to eq([record1, record2, record3, record4])
|
163
|
-
expect(record3.previous_items.to_a).to eq([record1, record2])
|
164
|
-
expect(record3.next_items.to_a).to eq([record4, record5])
|
165
|
-
expect(record1.next_item).to eq(record2)
|
166
|
-
expect(record2.previous_item).to eq(record1)
|
167
|
-
expect(record1.previous_item).to eq(nil)
|
168
|
-
expect(record5.next_item).to eq(nil)
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
context 'with transactions' do
|
174
|
-
enable_transactions!
|
175
|
-
|
176
|
-
it_behaves_like 'simple_orderable'
|
177
|
-
end
|
178
|
-
|
179
|
-
context 'without transactions' do
|
180
|
-
disable_transactions!
|
181
|
-
|
182
|
-
it_behaves_like 'simple_orderable'
|
183
|
-
end
|
184
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe StringScopedOrderable do
|
4
|
-
|
5
|
-
shared_examples_for 'string_scoped_orderable' do
|
6
|
-
|
7
|
-
it 'uses the foreign key of the relationship as scope' do
|
8
|
-
orderable1 = StringScopedOrderable.create!(some_scope: 1)
|
9
|
-
orderable2 = StringScopedOrderable.create!(some_scope: 1)
|
10
|
-
orderable3 = StringScopedOrderable.create!(some_scope: 2)
|
11
|
-
expect(orderable1.position).to eq 1
|
12
|
-
expect(orderable2.position).to eq 2
|
13
|
-
expect(orderable3.position).to eq 1
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
context 'with transactions' do
|
18
|
-
enable_transactions!
|
19
|
-
|
20
|
-
it_behaves_like 'string_scoped_orderable'
|
21
|
-
end
|
22
|
-
|
23
|
-
context 'without transactions' do
|
24
|
-
disable_transactions!
|
25
|
-
|
26
|
-
it_behaves_like 'string_scoped_orderable'
|
27
|
-
end
|
28
|
-
end
|
@@ -1,161 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ZeroBasedOrderable do
|
4
|
-
|
5
|
-
shared_examples_for 'zero_based_orderable' do
|
6
|
-
|
7
|
-
before :each do
|
8
|
-
5.times { ZeroBasedOrderable.create! }
|
9
|
-
end
|
10
|
-
|
11
|
-
def positions
|
12
|
-
ZeroBasedOrderable.pluck(:position).sort
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'should have a orderable base of 0' do
|
16
|
-
expect(ZeroBasedOrderable.create!.orderable_top).to eq(0)
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'should set proper position while creation' do
|
20
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
21
|
-
end
|
22
|
-
|
23
|
-
describe 'reset position' do
|
24
|
-
before { ZeroBasedOrderable.update_all(position: nil) }
|
25
|
-
it 'should properly reset position' do
|
26
|
-
ZeroBasedOrderable.all.map(&:save)
|
27
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
describe 'removement' do
|
32
|
-
it 'top' do
|
33
|
-
ZeroBasedOrderable.where(position: 0).destroy
|
34
|
-
expect(positions).to eq([0, 1, 2, 3])
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'bottom' do
|
38
|
-
ZeroBasedOrderable.where(position: 4).destroy
|
39
|
-
expect(positions).to eq([0, 1, 2, 3])
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'middle' do
|
43
|
-
ZeroBasedOrderable.where(position: 2).destroy
|
44
|
-
expect(positions).to eq([0, 1, 2, 3])
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
describe 'inserting' do
|
49
|
-
it 'top' do
|
50
|
-
newbie = ZeroBasedOrderable.create! move_to: :top
|
51
|
-
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
52
|
-
expect(newbie.position).to eq(0)
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'bottom' do
|
56
|
-
newbie = ZeroBasedOrderable.create! move_to: :bottom
|
57
|
-
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
58
|
-
expect(newbie.position).to eq(5)
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'middle' do
|
62
|
-
newbie = ZeroBasedOrderable.create! move_to: 3
|
63
|
-
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
64
|
-
expect(newbie.position).to eq(3)
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'middle (with a numeric string)' do
|
68
|
-
newbie = ZeroBasedOrderable.create! move_to: '3'
|
69
|
-
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
70
|
-
expect(newbie.position).to eq(3)
|
71
|
-
end
|
72
|
-
|
73
|
-
it 'middle (with a non-numeric string)' do
|
74
|
-
expect do
|
75
|
-
ZeroBasedOrderable.create! move_to: 'three'
|
76
|
-
end.to raise_error Mongoid::Orderable::Errors::InvalidTargetPosition
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
describe 'movement' do
|
81
|
-
it 'higher from top' do
|
82
|
-
record = ZeroBasedOrderable.where(position: 0).first
|
83
|
-
record.update_attributes move_to: :higher
|
84
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
85
|
-
expect(record.reload.position).to eq(0)
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'higher from bottom' do
|
89
|
-
record = ZeroBasedOrderable.where(position: 4).first
|
90
|
-
record.update_attributes move_to: :higher
|
91
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
92
|
-
expect(record.reload.position).to eq(3)
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'higher from middle' do
|
96
|
-
record = ZeroBasedOrderable.where(position: 3).first
|
97
|
-
record.update_attributes move_to: :higher
|
98
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
99
|
-
expect(record.reload.position).to eq(2)
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'lower from top' do
|
103
|
-
record = ZeroBasedOrderable.where(position: 0).first
|
104
|
-
record.update_attributes move_to: :lower
|
105
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
106
|
-
expect(record.reload.position).to eq(1)
|
107
|
-
end
|
108
|
-
|
109
|
-
it 'lower from bottom' do
|
110
|
-
record = ZeroBasedOrderable.where(position: 4).first
|
111
|
-
record.update_attributes move_to: :lower
|
112
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
113
|
-
expect(record.reload.position).to eq(4)
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'lower from middle' do
|
117
|
-
record = ZeroBasedOrderable.where(position: 2).first
|
118
|
-
record.update_attributes move_to: :lower
|
119
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
120
|
-
expect(record.reload.position).to eq(3)
|
121
|
-
end
|
122
|
-
|
123
|
-
it 'does nothing if position not change' do
|
124
|
-
record = ZeroBasedOrderable.where(position: 3).first
|
125
|
-
record.save
|
126
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
127
|
-
expect(record.reload.position).to eq(3)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
describe 'utility methods' do
|
132
|
-
it 'should return a collection of items lower/higher on the list for next_items/previous_items' do
|
133
|
-
record1 = ZeroBasedOrderable.where(position: 0).first
|
134
|
-
record2 = ZeroBasedOrderable.where(position: 1).first
|
135
|
-
record3 = ZeroBasedOrderable.where(position: 2).first
|
136
|
-
record4 = ZeroBasedOrderable.where(position: 3).first
|
137
|
-
record5 = ZeroBasedOrderable.where(position: 4).first
|
138
|
-
expect(record1.next_items.to_a).to eq([record2, record3, record4, record5])
|
139
|
-
expect(record5.previous_items.to_a).to eq([record1, record2, record3, record4])
|
140
|
-
expect(record3.previous_items.to_a).to eq([record1, record2])
|
141
|
-
expect(record3.next_items.to_a).to eq([record4, record5])
|
142
|
-
expect(record1.next_item).to eq(record2)
|
143
|
-
expect(record2.previous_item).to eq(record1)
|
144
|
-
expect(record1.previous_item).to eq(nil)
|
145
|
-
expect(record5.next_item).to eq(nil)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
context 'with transactions' do
|
151
|
-
enable_transactions!
|
152
|
-
|
153
|
-
it_behaves_like 'zero_based_orderable'
|
154
|
-
end
|
155
|
-
|
156
|
-
context 'without transactions' do
|
157
|
-
disable_transactions!
|
158
|
-
|
159
|
-
it_behaves_like 'zero_based_orderable'
|
160
|
-
end
|
161
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'bundler'
|
2
|
-
Bundler.require
|
3
|
-
require 'rspec'
|
4
|
-
require 'rspec/retry'
|
5
|
-
|
6
|
-
Mongoid.configure do |config|
|
7
|
-
config.connect_to 'mongoid_orderable_test'
|
8
|
-
end
|
9
|
-
|
10
|
-
Mongoid.logger.level = Logger::INFO
|
11
|
-
Mongo::Logger.logger.level = Logger::INFO
|
12
|
-
Mongoid::Config.belongs_to_required_by_default = false
|
13
|
-
|
14
|
-
RSpec.configure do |config|
|
15
|
-
config.order = 'random'
|
16
|
-
|
17
|
-
config.before(:each) do
|
18
|
-
Mongoid.purge!
|
19
|
-
Mongoid.models.each do |model|
|
20
|
-
model.create_indexes if model.name =~ /Mongoid::Orderable::Models/
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
require_relative 'support/models'
|
26
|
-
|
27
|
-
def set_transactions(enabled)
|
28
|
-
Mongoid.models.each do |model|
|
29
|
-
next unless model.respond_to?(:orderable_configs)
|
30
|
-
model.orderable_configs.values.each do |config|
|
31
|
-
config[:use_transactions] = enabled
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def enable_transactions!
|
37
|
-
before { set_transactions(true) }
|
38
|
-
end
|
39
|
-
|
40
|
-
def disable_transactions!
|
41
|
-
before { set_transactions(false) }
|
42
|
-
end
|
data/spec/support/models.rb
DELETED
@@ -1,134 +0,0 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
Mongoid::Orderable.configure do |c|
|
4
|
-
c.use_transactions = true
|
5
|
-
c.transaction_max_retries = 100
|
6
|
-
c.lock_collection = :foo_bar_locks
|
7
|
-
end
|
8
|
-
|
9
|
-
class SimpleOrderable
|
10
|
-
include Mongoid::Document
|
11
|
-
include Mongoid::Orderable
|
12
|
-
|
13
|
-
orderable
|
14
|
-
end
|
15
|
-
|
16
|
-
class ConditionalOrderable
|
17
|
-
include Mongoid::Document
|
18
|
-
include Mongoid::Orderable
|
19
|
-
|
20
|
-
field :cond_a, type: Boolean
|
21
|
-
field :cond_b, type: Integer
|
22
|
-
|
23
|
-
orderable field: :pos_a, if: :cond_a, unless: ->(obj) { obj.cond_b&.<(2) }
|
24
|
-
orderable field: :pos_b, if: -> { cond_b&.<=(4) }
|
25
|
-
orderable field: :pos_c, unless: false
|
26
|
-
end
|
27
|
-
|
28
|
-
class ScopedGroup
|
29
|
-
include Mongoid::Document
|
30
|
-
|
31
|
-
has_many :scoped_orderables
|
32
|
-
has_many :multiple_fields_orderables
|
33
|
-
end
|
34
|
-
|
35
|
-
class ScopedOrderable
|
36
|
-
include Mongoid::Document
|
37
|
-
include Mongoid::Orderable
|
38
|
-
|
39
|
-
belongs_to :group, class_name: 'ScopedGroup', optional: true
|
40
|
-
|
41
|
-
orderable scope: :group
|
42
|
-
end
|
43
|
-
|
44
|
-
class StringScopedOrderable
|
45
|
-
include Mongoid::Document
|
46
|
-
include Mongoid::Orderable
|
47
|
-
|
48
|
-
field :some_scope, type: Integer
|
49
|
-
|
50
|
-
orderable scope: 'some_scope'
|
51
|
-
end
|
52
|
-
|
53
|
-
class EmbedsOrderable
|
54
|
-
include Mongoid::Document
|
55
|
-
|
56
|
-
embeds_many :embedded_orderables, cascade_callbacks: true
|
57
|
-
end
|
58
|
-
|
59
|
-
class EmbeddedOrderable
|
60
|
-
include Mongoid::Document
|
61
|
-
include Mongoid::Orderable
|
62
|
-
|
63
|
-
embedded_in :embeds_orderable
|
64
|
-
|
65
|
-
orderable
|
66
|
-
end
|
67
|
-
|
68
|
-
class CustomizedOrderable
|
69
|
-
include Mongoid::Document
|
70
|
-
include Mongoid::Orderable
|
71
|
-
|
72
|
-
orderable field: :pos, as: :my_position
|
73
|
-
end
|
74
|
-
|
75
|
-
class NoIndexOrderable
|
76
|
-
include Mongoid::Document
|
77
|
-
include Mongoid::Orderable
|
78
|
-
|
79
|
-
orderable index: false
|
80
|
-
end
|
81
|
-
|
82
|
-
class ZeroBasedOrderable
|
83
|
-
include Mongoid::Document
|
84
|
-
include Mongoid::Orderable
|
85
|
-
|
86
|
-
orderable base: 0
|
87
|
-
end
|
88
|
-
|
89
|
-
class InheritedOrderable
|
90
|
-
include Mongoid::Document
|
91
|
-
include Mongoid::Orderable
|
92
|
-
|
93
|
-
orderable inherited: true
|
94
|
-
end
|
95
|
-
|
96
|
-
class Apple < InheritedOrderable
|
97
|
-
orderable field: :serial
|
98
|
-
end
|
99
|
-
|
100
|
-
class Orange < InheritedOrderable
|
101
|
-
end
|
102
|
-
|
103
|
-
class ForeignKeyDiffersOrderable
|
104
|
-
include Mongoid::Document
|
105
|
-
include Mongoid::Orderable
|
106
|
-
|
107
|
-
belongs_to :different_scope, class_name: 'ForeignKeyDiffersOrderable',
|
108
|
-
foreign_key: 'different_orderable_id',
|
109
|
-
optional: true
|
110
|
-
|
111
|
-
orderable scope: :different_scope
|
112
|
-
end
|
113
|
-
|
114
|
-
class MultipleFieldsOrderable
|
115
|
-
include Mongoid::Document
|
116
|
-
include Mongoid::Orderable
|
117
|
-
|
118
|
-
belongs_to :group, class_name: 'ScopedGroup', optional: true
|
119
|
-
|
120
|
-
orderable field: :pos, base: 0, index: false, as: :position
|
121
|
-
orderable field: :serial_no, default: true
|
122
|
-
orderable field: :groups, scope: :group
|
123
|
-
end
|
124
|
-
|
125
|
-
class MultipleScopedOrderable
|
126
|
-
include Mongoid::Document
|
127
|
-
include Mongoid::Orderable
|
128
|
-
|
129
|
-
belongs_to :apple, optional: true
|
130
|
-
belongs_to :orange, optional: true
|
131
|
-
|
132
|
-
orderable field: :posa, scope: :apple_id
|
133
|
-
orderable field: :poso, scope: :orange_id
|
134
|
-
end
|