mongoid_orderable 6.0.1 → 6.0.2

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.
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ describe MultipleScopedOrderable do
4
+
5
+ shared_examples_for 'multiple_scoped_orderable' do
6
+
7
+ before :each do
8
+ 3.times do
9
+ Apple.create
10
+ Orange.create
11
+ end
12
+ MultipleScopedOrderable.create! apple_id: 1, orange_id: 1
13
+ MultipleScopedOrderable.create! apple_id: 2, orange_id: 1
14
+ MultipleScopedOrderable.create! apple_id: 2, orange_id: 2
15
+ MultipleScopedOrderable.create! apple_id: 1, orange_id: 3
16
+ MultipleScopedOrderable.create! apple_id: 1, orange_id: 1
17
+ MultipleScopedOrderable.create! apple_id: 3, orange_id: 3
18
+ MultipleScopedOrderable.create! apple_id: 2, orange_id: 3
19
+ MultipleScopedOrderable.create! apple_id: 3, orange_id: 2
20
+ MultipleScopedOrderable.create! apple_id: 1, orange_id: 3
21
+ end
22
+
23
+ def apple_positions
24
+ MultipleScopedOrderable.order_by([:apple_id, :asc], [:posa, :asc]).map(&:posa)
25
+ end
26
+
27
+ def orange_positions
28
+ MultipleScopedOrderable.order_by([:orange_id, :asc], [:poso, :asc]).map(&:poso)
29
+ end
30
+
31
+ describe 'default positions' do
32
+ it { expect(apple_positions).to eq([1, 2, 3, 4, 1, 2, 3, 1, 2]) }
33
+ it { expect(orange_positions).to eq([1, 2, 3, 1, 2, 1, 2, 3, 4]) }
34
+ end
35
+
36
+ describe 'change the scope of the apple' do
37
+ let(:record) { MultipleScopedOrderable.first }
38
+ before do
39
+ record.update_attribute(:apple_id, 2)
40
+ end
41
+
42
+ it 'should properly set the apple positions' do
43
+ expect(apple_positions).to eq([1, 2, 3, 1, 2, 3, 4, 1, 2])
44
+ end
45
+
46
+ it 'should not affect the orange positions' do
47
+ expect(orange_positions).to eq([1, 2, 3, 1, 2, 1, 2, 3, 4])
48
+ end
49
+ end
50
+ end
51
+
52
+ context 'with transactions' do
53
+ enable_transactions!
54
+
55
+ it_behaves_like 'multiple_scoped_orderable'
56
+ end
57
+
58
+ context 'without transactions' do
59
+ disable_transactions!
60
+
61
+ it_behaves_like 'multiple_scoped_orderable'
62
+ end
63
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe NoIndexOrderable do
4
+
5
+ shared_examples_for 'no_index_orderable' do
6
+
7
+ it 'should not have index on position field' do
8
+ expect(NoIndexOrderable.index_specifications.detect {|spec| spec.key == :position }).to be_nil
9
+ end
10
+ end
11
+
12
+ context 'with transactions' do
13
+ enable_transactions!
14
+
15
+ it_behaves_like 'no_index_orderable'
16
+ end
17
+
18
+ context 'without transactions' do
19
+ disable_transactions!
20
+
21
+ it_behaves_like 'no_index_orderable'
22
+ end
23
+ end
@@ -0,0 +1,151 @@
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
@@ -0,0 +1,184 @@
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
@@ -0,0 +1,28 @@
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