mongoid_orderable 4.1.0 → 4.1.1
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 +5 -13
- data/.rvmrc +1 -1
- data/CHANGELOG.md +4 -0
- data/README.md +54 -0
- data/lib/config/locales/en.yml +9 -0
- data/lib/mongoid/orderable.rb +10 -227
- data/lib/mongoid/orderable/callbacks.rb +75 -0
- data/lib/mongoid/orderable/configuration.rb +60 -0
- data/lib/mongoid/orderable/errors.rb +2 -0
- data/lib/mongoid/orderable/errors/invalid_target_position.rb +18 -0
- data/lib/mongoid/orderable/errors/mongoid_orderable_error.rb +14 -0
- data/lib/mongoid/orderable/generator.rb +34 -0
- data/lib/mongoid/orderable/generator/helpers.rb +29 -0
- data/lib/mongoid/orderable/generator/listable.rb +41 -0
- data/lib/mongoid/orderable/generator/movable.rb +62 -0
- data/lib/mongoid/orderable/generator/position.rb +26 -0
- data/lib/mongoid/orderable/generator/scope.rb +17 -0
- data/lib/mongoid/orderable/helpers.rb +50 -0
- data/lib/mongoid/orderable/listable.rb +49 -0
- data/lib/mongoid/orderable/movable.rb +58 -0
- data/lib/mongoid/orderable/orderable_class.rb +51 -0
- data/lib/mongoid_orderable.rb +19 -0
- data/lib/mongoid_orderable/version.rb +1 -1
- data/spec/mongoid/orderable_spec.rb +885 -86
- metadata +27 -11
data/lib/mongoid_orderable.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
I18n.enforce_available_locales = false
|
3
|
+
I18n.load_path << File.join(File.dirname(__FILE__), 'config', 'locales', 'en.yml')
|
4
|
+
|
1
5
|
module MongoidOrderable
|
2
6
|
def self.mongoid2?
|
3
7
|
::Mongoid.const_defined? :Contexts
|
@@ -35,3 +39,18 @@ else
|
|
35
39
|
end
|
36
40
|
|
37
41
|
require 'mongoid/orderable'
|
42
|
+
require 'mongoid/orderable/errors'
|
43
|
+
require 'mongoid/orderable/configuration'
|
44
|
+
require 'mongoid/orderable/helpers'
|
45
|
+
require 'mongoid/orderable/callbacks'
|
46
|
+
require 'mongoid/orderable/listable'
|
47
|
+
require 'mongoid/orderable/movable'
|
48
|
+
|
49
|
+
require 'mongoid/orderable/generator/listable'
|
50
|
+
require 'mongoid/orderable/generator/movable'
|
51
|
+
require 'mongoid/orderable/generator/position'
|
52
|
+
require 'mongoid/orderable/generator/scope'
|
53
|
+
require 'mongoid/orderable/generator/helpers'
|
54
|
+
require 'mongoid/orderable/generator'
|
55
|
+
|
56
|
+
require 'mongoid/orderable/orderable_class'
|
@@ -13,6 +13,7 @@ describe Mongoid::Orderable do
|
|
13
13
|
include Mongoid::Document
|
14
14
|
|
15
15
|
has_many :scoped_orderables
|
16
|
+
has_many :multiple_columns_orderables
|
16
17
|
end
|
17
18
|
|
18
19
|
class ScopedOrderable
|
@@ -93,6 +94,30 @@ describe Mongoid::Orderable do
|
|
93
94
|
orderable :scope => :different_scope
|
94
95
|
end
|
95
96
|
|
97
|
+
class MultipleColumnsOrderable
|
98
|
+
include Mongoid::Document
|
99
|
+
include Mongoid::Orderable
|
100
|
+
|
101
|
+
field :group_id
|
102
|
+
|
103
|
+
belongs_to :scoped_group
|
104
|
+
|
105
|
+
orderable :column => :pos, :base => 0, :index => false, :as => :position
|
106
|
+
orderable :column => :serial_no, :default => true
|
107
|
+
orderable :column => :groups, :scope => :group
|
108
|
+
end
|
109
|
+
|
110
|
+
class MultipleScopedOrderable
|
111
|
+
include Mongoid::Document
|
112
|
+
include Mongoid::Orderable
|
113
|
+
|
114
|
+
belongs_to :apple
|
115
|
+
belongs_to :orange
|
116
|
+
|
117
|
+
orderable :column => :posa, :scope => :apple_id
|
118
|
+
orderable :column => :poso, :scope => :orange_id
|
119
|
+
end
|
120
|
+
|
96
121
|
describe SimpleOrderable do
|
97
122
|
|
98
123
|
before :each do
|
@@ -107,43 +132,43 @@ describe Mongoid::Orderable do
|
|
107
132
|
end
|
108
133
|
|
109
134
|
it 'should have proper position column' do
|
110
|
-
SimpleOrderable.fields.key?('position').
|
111
|
-
SimpleOrderable.fields['position'].options[:type].
|
135
|
+
expect(SimpleOrderable.fields.key?('position')).to be true
|
136
|
+
expect(SimpleOrderable.fields['position'].options[:type]).to eq(Integer)
|
112
137
|
end
|
113
138
|
|
114
139
|
it 'should have index on position column' do
|
115
140
|
if MongoidOrderable.mongoid2?
|
116
|
-
SimpleOrderable.index_options[:position].
|
141
|
+
expect(SimpleOrderable.index_options[[[:position, 1]]]).not_to be_nil
|
117
142
|
elsif MongoidOrderable.mongoid3?
|
118
|
-
SimpleOrderable.index_options[{:position => 1}].
|
143
|
+
expect(SimpleOrderable.index_options[{:position => 1}]).not_to be_nil
|
119
144
|
else
|
120
|
-
SimpleOrderable.index_specifications.detect { |spec| spec.key == {:position => 1} }.
|
145
|
+
expect(SimpleOrderable.index_specifications.detect { |spec| spec.key == {:position => 1} }).not_to be_nil
|
121
146
|
end
|
122
147
|
end
|
123
148
|
|
124
149
|
it 'should have a orderable base of 1' do
|
125
|
-
SimpleOrderable.create!.orderable_base.
|
150
|
+
expect(SimpleOrderable.create!.orderable_base).to eq(1)
|
126
151
|
end
|
127
152
|
|
128
153
|
it 'should set proper position while creation' do
|
129
|
-
positions.
|
154
|
+
expect(positions).to eq([1, 2, 3, 4, 5])
|
130
155
|
end
|
131
156
|
|
132
157
|
describe 'removement' do
|
133
158
|
|
134
159
|
it 'top' do
|
135
160
|
SimpleOrderable.where(:position => 1).destroy
|
136
|
-
positions.
|
161
|
+
expect(positions).to eq([1, 2, 3, 4])
|
137
162
|
end
|
138
163
|
|
139
164
|
it 'bottom' do
|
140
165
|
SimpleOrderable.where(:position => 5).destroy
|
141
|
-
positions.
|
166
|
+
expect(positions).to eq([1, 2, 3, 4])
|
142
167
|
end
|
143
168
|
|
144
169
|
it 'middle' do
|
145
170
|
SimpleOrderable.where(:position => 3).destroy
|
146
|
-
positions.
|
171
|
+
expect(positions).to eq([1, 2, 3, 4])
|
147
172
|
end
|
148
173
|
end
|
149
174
|
|
@@ -151,20 +176,32 @@ describe Mongoid::Orderable do
|
|
151
176
|
|
152
177
|
it 'top' do
|
153
178
|
newbie = SimpleOrderable.create! :move_to => :top
|
154
|
-
positions.
|
155
|
-
newbie.position.
|
179
|
+
expect(positions).to eq([1, 2, 3, 4, 5, 6])
|
180
|
+
expect(newbie.position).to eq(1)
|
156
181
|
end
|
157
182
|
|
158
183
|
it 'bottom' do
|
159
184
|
newbie = SimpleOrderable.create! :move_to => :bottom
|
160
|
-
positions.
|
161
|
-
newbie.position.
|
185
|
+
expect(positions).to eq([1, 2, 3, 4, 5, 6])
|
186
|
+
expect(newbie.position).to eq(6)
|
162
187
|
end
|
163
188
|
|
164
189
|
it 'middle' do
|
165
190
|
newbie = SimpleOrderable.create! :move_to => 4
|
166
|
-
positions.
|
167
|
-
newbie.position.
|
191
|
+
expect(positions).to eq([1, 2, 3, 4, 5, 6])
|
192
|
+
expect(newbie.position).to eq(4)
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'middle (with a numeric string)' do
|
196
|
+
newbie = SimpleOrderable.create! :move_to => '4'
|
197
|
+
expect(positions).to eq([1, 2, 3, 4, 5, 6])
|
198
|
+
expect(newbie.position).to eq(4)
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'middle (with a non-numeric string)' do
|
202
|
+
expect do
|
203
|
+
SimpleOrderable.create! :move_to => 'four'
|
204
|
+
end.to raise_error Mongoid::Orderable::Errors::InvalidTargetPosition
|
168
205
|
end
|
169
206
|
end
|
170
207
|
|
@@ -173,50 +210,50 @@ describe Mongoid::Orderable do
|
|
173
210
|
it 'higher from top' do
|
174
211
|
record = SimpleOrderable.where(:position => 1).first
|
175
212
|
record.update_attributes :move_to => :higher
|
176
|
-
positions.
|
177
|
-
record.reload.position.
|
213
|
+
expect(positions).to eq([1, 2, 3, 4, 5])
|
214
|
+
expect(record.reload.position).to eq(1)
|
178
215
|
end
|
179
216
|
|
180
217
|
it 'higher from bottom' do
|
181
218
|
record = SimpleOrderable.where(:position => 5).first
|
182
219
|
record.update_attributes :move_to => :higher
|
183
|
-
positions.
|
184
|
-
record.reload.position.
|
220
|
+
expect(positions).to eq([1, 2, 3, 4, 5])
|
221
|
+
expect(record.reload.position).to eq(4)
|
185
222
|
end
|
186
223
|
|
187
224
|
it 'higher from middle' do
|
188
225
|
record = SimpleOrderable.where(:position => 3).first
|
189
226
|
record.update_attributes :move_to => :higher
|
190
|
-
positions.
|
191
|
-
record.reload.position.
|
227
|
+
expect(positions).to eq([1, 2, 3, 4, 5])
|
228
|
+
expect(record.reload.position).to eq(2)
|
192
229
|
end
|
193
230
|
|
194
231
|
it 'lower from top' do
|
195
232
|
record = SimpleOrderable.where(:position => 1).first
|
196
233
|
record.update_attributes :move_to => :lower
|
197
|
-
positions.
|
198
|
-
record.reload.position.
|
234
|
+
expect(positions).to eq([1, 2, 3, 4, 5])
|
235
|
+
expect(record.reload.position).to eq(2)
|
199
236
|
end
|
200
237
|
|
201
238
|
it 'lower from bottom' do
|
202
239
|
record = SimpleOrderable.where(:position => 5).first
|
203
240
|
record.update_attributes :move_to => :lower
|
204
|
-
positions.
|
205
|
-
record.reload.position.
|
241
|
+
expect(positions).to eq([1, 2, 3, 4, 5])
|
242
|
+
expect(record.reload.position).to eq(5)
|
206
243
|
end
|
207
244
|
|
208
245
|
it 'lower from middle' do
|
209
246
|
record = SimpleOrderable.where(:position => 3).first
|
210
247
|
record.update_attributes :move_to => :lower
|
211
|
-
positions.
|
212
|
-
record.reload.position.
|
248
|
+
expect(positions).to eq([1, 2, 3, 4, 5])
|
249
|
+
expect(record.reload.position).to eq(4)
|
213
250
|
end
|
214
251
|
|
215
252
|
it 'does nothing if position not change' do
|
216
253
|
record = SimpleOrderable.where(:position => 3).first
|
217
254
|
record.save
|
218
|
-
positions.
|
219
|
-
record.reload.position.
|
255
|
+
expect(positions).to eq([1, 2, 3, 4, 5])
|
256
|
+
expect(record.reload.position).to eq(3)
|
220
257
|
end
|
221
258
|
end
|
222
259
|
|
@@ -253,24 +290,24 @@ describe Mongoid::Orderable do
|
|
253
290
|
end
|
254
291
|
|
255
292
|
it 'should set proper position while creation' do
|
256
|
-
positions.
|
293
|
+
expect(positions).to eq([1, 2, 1, 2, 3])
|
257
294
|
end
|
258
295
|
|
259
296
|
describe 'removement' do
|
260
297
|
|
261
298
|
it 'top' do
|
262
299
|
ScopedOrderable.where(:position => 1, :group_id => 1).destroy
|
263
|
-
positions.
|
300
|
+
expect(positions).to eq([1, 1, 2, 3])
|
264
301
|
end
|
265
302
|
|
266
303
|
it 'bottom' do
|
267
304
|
ScopedOrderable.where(:position => 3, :group_id => 2).destroy
|
268
|
-
positions.
|
305
|
+
expect(positions).to eq([1, 2, 1, 2])
|
269
306
|
end
|
270
307
|
|
271
308
|
it 'middle' do
|
272
309
|
ScopedOrderable.where(:position => 2, :group_id => 2).destroy
|
273
|
-
positions.
|
310
|
+
expect(positions).to eq([1, 2, 1, 2])
|
274
311
|
end
|
275
312
|
end
|
276
313
|
|
@@ -278,20 +315,55 @@ describe Mongoid::Orderable do
|
|
278
315
|
|
279
316
|
it 'top' do
|
280
317
|
newbie = ScopedOrderable.create! :move_to => :top, :group_id => 1
|
281
|
-
positions.
|
282
|
-
newbie.position.
|
318
|
+
expect(positions).to eq([1, 2, 3, 1, 2, 3])
|
319
|
+
expect(newbie.position).to eq(1)
|
283
320
|
end
|
284
321
|
|
285
322
|
it 'bottom' do
|
286
323
|
newbie = ScopedOrderable.create! :move_to => :bottom, :group_id => 2
|
287
|
-
positions.
|
288
|
-
newbie.position.
|
324
|
+
expect(positions).to eq([1, 2, 1, 2, 3, 4])
|
325
|
+
expect(newbie.position).to eq(4)
|
289
326
|
end
|
290
327
|
|
291
328
|
it 'middle' do
|
292
329
|
newbie = ScopedOrderable.create! :move_to => 2, :group_id => 2
|
293
|
-
positions.
|
294
|
-
newbie.position.
|
330
|
+
expect(positions).to eq([1, 2, 1, 2, 3, 4])
|
331
|
+
expect(newbie.position).to eq(2)
|
332
|
+
end
|
333
|
+
|
334
|
+
it 'middle (with a numeric string)' do
|
335
|
+
newbie = ScopedOrderable.create! :move_to => '2', :group_id => 2
|
336
|
+
expect(positions).to eq([1, 2, 1, 2, 3, 4])
|
337
|
+
expect(newbie.position).to eq(2)
|
338
|
+
end
|
339
|
+
|
340
|
+
it 'middle (with a non-numeric string)' do
|
341
|
+
expect do
|
342
|
+
ScopedOrderable.create! :move_to => 'two', :group_id => 2
|
343
|
+
end.to raise_error Mongoid::Orderable::Errors::InvalidTargetPosition
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
describe 'index' do
|
348
|
+
|
349
|
+
it 'is not on position alone' do
|
350
|
+
if MongoidOrderable.mongoid2?
|
351
|
+
expect(ScopedOrderable.index_options[[[:position, 1]]]).to be_nil
|
352
|
+
elsif MongoidOrderable.mongoid3?
|
353
|
+
expect(ScopedOrderable.index_options[{:position => 1}]).to be_nil
|
354
|
+
else
|
355
|
+
expect(ScopedOrderable.index_specifications.detect { |spec| spec.key == {:position => 1} }).to be_nil
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
it 'is on compound fields' do
|
360
|
+
if MongoidOrderable.mongoid2?
|
361
|
+
expect(ScopedOrderable.index_options[[[:group_id, 1], [:position, 1]]]).to_not be_nil
|
362
|
+
elsif MongoidOrderable.mongoid3?
|
363
|
+
expect(ScopedOrderable.index_options[{:group_id => 1, :position => 1}]).to_not be_nil
|
364
|
+
else
|
365
|
+
expect(ScopedOrderable.index_specifications.detect { |spec| spec.key == {:group_id => 1, :position => 1} }).to_not be_nil
|
366
|
+
end
|
295
367
|
end
|
296
368
|
end
|
297
369
|
|
@@ -301,28 +373,40 @@ describe Mongoid::Orderable do
|
|
301
373
|
|
302
374
|
it 'to a new scope group' do
|
303
375
|
record.update_attributes :group_id => 3
|
304
|
-
positions.
|
305
|
-
record.position.
|
376
|
+
expect(positions).to eq([1, 2, 1, 2, 1])
|
377
|
+
expect(record.position).to eq(1)
|
306
378
|
end
|
307
379
|
|
308
380
|
context 'when moving to an existing scope group' do
|
309
381
|
|
310
382
|
it 'without a position' do
|
311
383
|
record.update_attributes :group_id => 1
|
312
|
-
positions.
|
313
|
-
record.reload.position.
|
384
|
+
expect(positions).to eq([1, 2, 3, 1, 2])
|
385
|
+
expect(record.reload.position).to eq(3)
|
314
386
|
end
|
315
387
|
|
316
388
|
it 'with symbol position' do
|
317
389
|
record.update_attributes :group_id => 1, :move_to => :top
|
318
|
-
positions.
|
319
|
-
record.reload.position.
|
390
|
+
expect(positions).to eq([1, 2, 3, 1, 2])
|
391
|
+
expect(record.reload.position).to eq(1)
|
320
392
|
end
|
321
393
|
|
322
394
|
it 'with point position' do
|
323
395
|
record.update_attributes :group_id => 1, :move_to => 2
|
324
|
-
positions.
|
325
|
-
record.reload.position.
|
396
|
+
expect(positions).to eq([1, 2, 3, 1, 2])
|
397
|
+
expect(record.reload.position).to eq(2)
|
398
|
+
end
|
399
|
+
|
400
|
+
it 'with point position (with a numeric string)' do
|
401
|
+
record.update_attributes :group_id => 1, :move_to => '2'
|
402
|
+
expect(positions).to eq([1, 2, 3, 1, 2])
|
403
|
+
expect(record.reload.position).to eq(2)
|
404
|
+
end
|
405
|
+
|
406
|
+
it 'with point position (with a non-numeric string)' do
|
407
|
+
expect do
|
408
|
+
record.update_attributes :group_id => 1, :move_to => 'two'
|
409
|
+
end.to raise_error Mongoid::Orderable::Errors::InvalidTargetPosition
|
326
410
|
end
|
327
411
|
end
|
328
412
|
end
|
@@ -344,14 +428,26 @@ describe Mongoid::Orderable do
|
|
344
428
|
|
345
429
|
it 'to a new scope group' do
|
346
430
|
record.update_attributes :group_id => 3
|
347
|
-
positions.
|
348
|
-
record.position.
|
431
|
+
expect(positions).to eq([1, 2, 1, 2, 1])
|
432
|
+
expect(record.position).to eq(1)
|
349
433
|
end
|
350
434
|
|
351
435
|
it 'to an existing scope group' do
|
352
436
|
record.update_attributes :group_id => 1, :move_to => 2
|
353
|
-
positions.
|
354
|
-
record.reload.position.
|
437
|
+
expect(positions).to eq([1, 2, 3, 1, 2])
|
438
|
+
expect(record.reload.position).to eq(2)
|
439
|
+
end
|
440
|
+
|
441
|
+
it 'to an existing scope group (with a numeric string)' do
|
442
|
+
record.update_attributes :group_id => 1, :move_to => '2'
|
443
|
+
expect(positions).to eq([1, 2, 3, 1, 2])
|
444
|
+
expect(record.reload.position).to eq(2)
|
445
|
+
end
|
446
|
+
|
447
|
+
it 'to an existing scope group (with a non-numeric string)' do
|
448
|
+
expect do
|
449
|
+
record.update_attributes :group_id => 1, :move_to => 'two'
|
450
|
+
end.to raise_error Mongoid::Orderable::Errors::InvalidTargetPosition
|
355
451
|
end
|
356
452
|
end
|
357
453
|
end
|
@@ -408,30 +504,30 @@ describe Mongoid::Orderable do
|
|
408
504
|
end
|
409
505
|
|
410
506
|
it 'sets proper position while creation' do
|
411
|
-
positions.
|
507
|
+
expect(positions).to eq([[1, 2], [1, 2, 3]])
|
412
508
|
end
|
413
509
|
|
414
510
|
it 'moves an item returned by a query to position' do
|
415
511
|
embedded_orderable_1 = EmbedsOrderable.first.embedded_orderables.where(:position => 1).first
|
416
512
|
embedded_orderable_2 = EmbedsOrderable.first.embedded_orderables.where(:position => 2).first
|
417
513
|
embedded_orderable_1.move_to! 2
|
418
|
-
embedded_orderable_2.reload.position.
|
514
|
+
expect(embedded_orderable_2.reload.position).to eq(1)
|
419
515
|
end
|
420
516
|
end
|
421
517
|
|
422
518
|
describe CustomizedOrderable do
|
423
519
|
|
424
520
|
it 'does not have default position field' do
|
425
|
-
CustomizedOrderable.fields.
|
521
|
+
expect(CustomizedOrderable.fields).not_to have_key('position')
|
426
522
|
end
|
427
523
|
|
428
524
|
it 'should have custom pos field' do
|
429
|
-
CustomizedOrderable.fields.
|
525
|
+
expect(CustomizedOrderable.fields).to have_key('pos')
|
430
526
|
end
|
431
527
|
|
432
528
|
it 'should have an alias my_position which points to pos field on Mongoid 3+' do
|
433
529
|
if CustomizedOrderable.respond_to?(:database_field_name)
|
434
|
-
CustomizedOrderable.database_field_name('my_position').
|
530
|
+
expect(CustomizedOrderable.database_field_name('my_position')).to eq('pos')
|
435
531
|
end
|
436
532
|
end
|
437
533
|
end
|
@@ -440,9 +536,9 @@ describe Mongoid::Orderable do
|
|
440
536
|
|
441
537
|
it 'should not have index on position column' do
|
442
538
|
if MongoidOrderable.mongoid2? || MongoidOrderable.mongoid3?
|
443
|
-
NoIndexOrderable.index_options[:position].
|
539
|
+
expect(NoIndexOrderable.index_options[[[:position, 1]]]).to be_nil
|
444
540
|
else
|
445
|
-
NoIndexOrderable.index_specifications.detect { |spec| spec.key == :position }.
|
541
|
+
expect(NoIndexOrderable.index_specifications.detect { |spec| spec.key == :position }).to be_nil
|
446
542
|
end
|
447
543
|
end
|
448
544
|
end
|
@@ -461,28 +557,36 @@ describe Mongoid::Orderable do
|
|
461
557
|
end
|
462
558
|
|
463
559
|
it 'should have a orderable base of 0' do
|
464
|
-
ZeroBasedOrderable.create!.orderable_base.
|
560
|
+
expect(ZeroBasedOrderable.create!.orderable_base).to eq(0)
|
465
561
|
end
|
466
562
|
|
467
563
|
it 'should set proper position while creation' do
|
468
|
-
positions.
|
564
|
+
expect(positions).to eq([0, 1, 2, 3, 4])
|
565
|
+
end
|
566
|
+
|
567
|
+
describe 'reset position' do
|
568
|
+
before{ ZeroBasedOrderable.update_all({:position => nil}) }
|
569
|
+
it 'should properly reset position' do
|
570
|
+
ZeroBasedOrderable.all.map(&:save)
|
571
|
+
expect(positions).to eq([0, 1, 2, 3, 4])
|
572
|
+
end
|
469
573
|
end
|
470
574
|
|
471
575
|
describe 'removement' do
|
472
576
|
|
473
577
|
it 'top' do
|
474
578
|
ZeroBasedOrderable.where(:position => 0).destroy
|
475
|
-
positions.
|
579
|
+
expect(positions).to eq([0, 1, 2, 3])
|
476
580
|
end
|
477
581
|
|
478
582
|
it 'bottom' do
|
479
583
|
ZeroBasedOrderable.where(:position => 4).destroy
|
480
|
-
positions.
|
584
|
+
expect(positions).to eq([0, 1, 2, 3])
|
481
585
|
end
|
482
586
|
|
483
587
|
it 'middle' do
|
484
588
|
ZeroBasedOrderable.where(:position => 2).destroy
|
485
|
-
positions.
|
589
|
+
expect(positions).to eq([0, 1, 2, 3])
|
486
590
|
end
|
487
591
|
end
|
488
592
|
|
@@ -490,20 +594,32 @@ describe Mongoid::Orderable do
|
|
490
594
|
|
491
595
|
it 'top' do
|
492
596
|
newbie = ZeroBasedOrderable.create! :move_to => :top
|
493
|
-
positions.
|
494
|
-
newbie.position.
|
597
|
+
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
598
|
+
expect(newbie.position).to eq(0)
|
495
599
|
end
|
496
600
|
|
497
601
|
it 'bottom' do
|
498
602
|
newbie = ZeroBasedOrderable.create! :move_to => :bottom
|
499
|
-
positions.
|
500
|
-
newbie.position.
|
603
|
+
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
604
|
+
expect(newbie.position).to eq(5)
|
501
605
|
end
|
502
606
|
|
503
607
|
it 'middle' do
|
504
608
|
newbie = ZeroBasedOrderable.create! :move_to => 3
|
505
|
-
positions.
|
506
|
-
newbie.position.
|
609
|
+
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
610
|
+
expect(newbie.position).to eq(3)
|
611
|
+
end
|
612
|
+
|
613
|
+
it 'middle (with a numeric string)' do
|
614
|
+
newbie = ZeroBasedOrderable.create! :move_to => '3'
|
615
|
+
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
616
|
+
expect(newbie.position).to eq(3)
|
617
|
+
end
|
618
|
+
|
619
|
+
it 'middle (with a non-numeric string)' do
|
620
|
+
expect do
|
621
|
+
ZeroBasedOrderable.create! :move_to => 'three'
|
622
|
+
end.to raise_error Mongoid::Orderable::Errors::InvalidTargetPosition
|
507
623
|
end
|
508
624
|
end
|
509
625
|
|
@@ -512,50 +628,50 @@ describe Mongoid::Orderable do
|
|
512
628
|
it 'higher from top' do
|
513
629
|
record = ZeroBasedOrderable.where(:position => 0).first
|
514
630
|
record.update_attributes :move_to => :higher
|
515
|
-
positions.
|
516
|
-
record.reload.position.
|
631
|
+
expect(positions).to eq([0, 1, 2, 3, 4])
|
632
|
+
expect(record.reload.position).to eq(0)
|
517
633
|
end
|
518
634
|
|
519
635
|
it 'higher from bottom' do
|
520
636
|
record = ZeroBasedOrderable.where(:position => 4).first
|
521
637
|
record.update_attributes :move_to => :higher
|
522
|
-
positions.
|
523
|
-
record.reload.position.
|
638
|
+
expect(positions).to eq([0, 1, 2, 3, 4])
|
639
|
+
expect(record.reload.position).to eq(3)
|
524
640
|
end
|
525
641
|
|
526
642
|
it 'higher from middle' do
|
527
643
|
record = ZeroBasedOrderable.where(:position => 3).first
|
528
644
|
record.update_attributes :move_to => :higher
|
529
|
-
positions.
|
530
|
-
record.reload.position.
|
645
|
+
expect(positions).to eq([0, 1, 2, 3, 4])
|
646
|
+
expect(record.reload.position).to eq(2)
|
531
647
|
end
|
532
648
|
|
533
649
|
it 'lower from top' do
|
534
650
|
record = ZeroBasedOrderable.where(:position => 0).first
|
535
651
|
record.update_attributes :move_to => :lower
|
536
|
-
positions.
|
537
|
-
record.reload.position.
|
652
|
+
expect(positions).to eq([0, 1, 2, 3, 4])
|
653
|
+
expect(record.reload.position).to eq(1)
|
538
654
|
end
|
539
655
|
|
540
656
|
it 'lower from bottom' do
|
541
657
|
record = ZeroBasedOrderable.where(:position => 4).first
|
542
658
|
record.update_attributes :move_to => :lower
|
543
|
-
positions.
|
544
|
-
record.reload.position.
|
659
|
+
expect(positions).to eq([0, 1, 2, 3, 4])
|
660
|
+
expect(record.reload.position).to eq(4)
|
545
661
|
end
|
546
662
|
|
547
663
|
it 'lower from middle' do
|
548
664
|
record = ZeroBasedOrderable.where(:position => 2).first
|
549
665
|
record.update_attributes :move_to => :lower
|
550
|
-
positions.
|
551
|
-
record.reload.position.
|
666
|
+
expect(positions).to eq([0, 1, 2, 3, 4])
|
667
|
+
expect(record.reload.position).to eq(3)
|
552
668
|
end
|
553
669
|
|
554
670
|
it 'does nothing if position not change' do
|
555
671
|
record = ZeroBasedOrderable.where(:position => 3).first
|
556
672
|
record.save
|
557
|
-
positions.
|
558
|
-
record.reload.position.
|
673
|
+
expect(positions).to eq([0, 1, 2, 3, 4])
|
674
|
+
expect(record.reload.position).to eq(3)
|
559
675
|
end
|
560
676
|
end
|
561
677
|
|
@@ -585,8 +701,46 @@ describe Mongoid::Orderable do
|
|
585
701
|
it 'should set proper position' do
|
586
702
|
fruit1 = Apple.create
|
587
703
|
fruit2 = Orange.create
|
588
|
-
fruit1.position.
|
589
|
-
fruit2.position.
|
704
|
+
expect(fruit1.position).to eq(1)
|
705
|
+
expect(fruit2.position).to eq(2)
|
706
|
+
end
|
707
|
+
|
708
|
+
describe 'movement' do
|
709
|
+
before :each do
|
710
|
+
Fruit.delete_all
|
711
|
+
5.times do
|
712
|
+
Apple.create!
|
713
|
+
end
|
714
|
+
end
|
715
|
+
|
716
|
+
it 'with symbol position' do
|
717
|
+
first_apple = Apple.first
|
718
|
+
top_pos = first_apple.position
|
719
|
+
bottom_pos = Apple.last.position
|
720
|
+
expect do
|
721
|
+
first_apple.move_to! :bottom
|
722
|
+
end.to change(first_apple, :position).from(top_pos).to bottom_pos
|
723
|
+
end
|
724
|
+
|
725
|
+
it 'with point position' do
|
726
|
+
first_apple = Apple.first
|
727
|
+
top_pos = first_apple.position
|
728
|
+
bottom_pos = Apple.last.position
|
729
|
+
expect do
|
730
|
+
first_apple.move_to! bottom_pos
|
731
|
+
end.to change(first_apple, :position).from(top_pos).to bottom_pos
|
732
|
+
end
|
733
|
+
end
|
734
|
+
|
735
|
+
describe 'add orderable configurations in inherited class' do
|
736
|
+
it 'does not affect the orderable configurations of parent class and sibling class' do
|
737
|
+
class Apple
|
738
|
+
orderable :column => :serial
|
739
|
+
end
|
740
|
+
expect(Fruit.orderable_configurations).not_to eq Apple.orderable_configurations
|
741
|
+
expect(Orange.orderable_configurations).not_to eq Apple.orderable_configurations
|
742
|
+
expect(Fruit.orderable_configurations).to eq Orange.orderable_configurations
|
743
|
+
end
|
590
744
|
end
|
591
745
|
end
|
592
746
|
|
@@ -606,4 +760,649 @@ describe Mongoid::Orderable do
|
|
606
760
|
expect(orderable3.position).to eq 1
|
607
761
|
end
|
608
762
|
end
|
763
|
+
|
764
|
+
describe MultipleColumnsOrderable do
|
765
|
+
|
766
|
+
before :each do
|
767
|
+
MultipleColumnsOrderable.delete_all
|
768
|
+
5.times do
|
769
|
+
MultipleColumnsOrderable.create!
|
770
|
+
end
|
771
|
+
end
|
772
|
+
|
773
|
+
context 'default orderable' do
|
774
|
+
let(:serial_nos){ MultipleColumnsOrderable.all.map(&:serial_no).sort }
|
775
|
+
|
776
|
+
describe 'inserting' do
|
777
|
+
let(:newbie){ MultipleColumnsOrderable.create! }
|
778
|
+
|
779
|
+
before { @position = newbie.position }
|
780
|
+
|
781
|
+
it 'top' do
|
782
|
+
newbie.move_to! :top
|
783
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5, 6])
|
784
|
+
expect(newbie.serial_no).to eq(1)
|
785
|
+
expect(newbie.position).to eq(@position)
|
786
|
+
end
|
787
|
+
|
788
|
+
it 'bottom' do
|
789
|
+
newbie.move_to! :bottom
|
790
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5, 6])
|
791
|
+
expect(newbie.serial_no).to eq(6)
|
792
|
+
expect(newbie.position).to eq(@position)
|
793
|
+
end
|
794
|
+
|
795
|
+
it 'middle' do
|
796
|
+
newbie.move_to! 4
|
797
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5, 6])
|
798
|
+
expect(newbie.serial_no).to eq(4)
|
799
|
+
expect(newbie.position).to eq(@position)
|
800
|
+
end
|
801
|
+
end
|
802
|
+
|
803
|
+
describe 'movement' do
|
804
|
+
it 'higher from top' do
|
805
|
+
record = MultipleColumnsOrderable.where(:serial_no => 1).first
|
806
|
+
position = record.position
|
807
|
+
record.move_higher!
|
808
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
809
|
+
expect(record.serial_no).to eq(1)
|
810
|
+
expect(record.position).to eq(position)
|
811
|
+
end
|
812
|
+
|
813
|
+
it 'higher from bottom' do
|
814
|
+
record = MultipleColumnsOrderable.where(:serial_no => 5).first
|
815
|
+
position = record.position
|
816
|
+
record.move_higher!
|
817
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
818
|
+
expect(record.serial_no).to eq(4)
|
819
|
+
expect(record.position).to eq(position)
|
820
|
+
end
|
821
|
+
|
822
|
+
it 'higher from middle' do
|
823
|
+
record = MultipleColumnsOrderable.where(:serial_no => 3).first
|
824
|
+
position = record.position
|
825
|
+
record.move_higher!
|
826
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
827
|
+
expect(record.serial_no).to eq(2)
|
828
|
+
expect(record.position).to eq(position)
|
829
|
+
end
|
830
|
+
|
831
|
+
it 'lower from top' do
|
832
|
+
record = MultipleColumnsOrderable.where(:serial_no => 1).first
|
833
|
+
position = record.position
|
834
|
+
record.move_lower!
|
835
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
836
|
+
expect(record.serial_no).to eq(2)
|
837
|
+
expect(record.position).to eq(position)
|
838
|
+
end
|
839
|
+
|
840
|
+
it 'lower from bottom' do
|
841
|
+
record = MultipleColumnsOrderable.where(:serial_no => 5).first
|
842
|
+
position = record.position
|
843
|
+
record.move_lower!
|
844
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
845
|
+
expect(record.serial_no).to eq(5)
|
846
|
+
expect(record.position).to eq(position)
|
847
|
+
end
|
848
|
+
|
849
|
+
it 'lower from middle' do
|
850
|
+
record = MultipleColumnsOrderable.where(:serial_no => 3).first
|
851
|
+
position = record.position
|
852
|
+
record.move_lower!
|
853
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
854
|
+
expect(record.serial_no).to eq(4)
|
855
|
+
expect(record.position).to eq(position)
|
856
|
+
end
|
857
|
+
end
|
858
|
+
|
859
|
+
describe 'utility methods' do
|
860
|
+
|
861
|
+
before do
|
862
|
+
@record_1 = MultipleColumnsOrderable.where(:serial_no => 1).first
|
863
|
+
@record_2 = MultipleColumnsOrderable.where(:serial_no => 2).first
|
864
|
+
@record_3 = MultipleColumnsOrderable.where(:serial_no => 3).first
|
865
|
+
@record_4 = MultipleColumnsOrderable.where(:serial_no => 4).first
|
866
|
+
@record_5 = MultipleColumnsOrderable.where(:serial_no => 5).first
|
867
|
+
end
|
868
|
+
|
869
|
+
it "should return the lower/higher item on the list for next_item/previous_item" do
|
870
|
+
expect(@record_1.next_item).to eq(@record_2)
|
871
|
+
expect(@record_3.next_item).to eq(@record_4)
|
872
|
+
expect(@record_5.next_item).to eq(nil)
|
873
|
+
expect(@record_1.prev_item).to eq(nil)
|
874
|
+
expect(@record_3.prev_item).to eq(@record_2)
|
875
|
+
expect(@record_5.prev_item).to eq(@record_4)
|
876
|
+
end
|
877
|
+
|
878
|
+
it "should return a collection of items lower/higher on the list for next_items/previous_items" do
|
879
|
+
expect(@record_1.next_items.to_a).to eq([@record_2, @record_3, @record_4, @record_5])
|
880
|
+
expect(@record_3.next_items.to_a).to eq([@record_4, @record_5])
|
881
|
+
expect(@record_5.next_items.to_a).to eq([])
|
882
|
+
expect(@record_1.previous_items.to_a).to eq([])
|
883
|
+
expect(@record_3.previous_items.to_a).to eq([@record_1, @record_2])
|
884
|
+
expect(@record_5.previous_items.to_a).to eq([@record_1, @record_2, @record_3, @record_4])
|
885
|
+
end
|
886
|
+
end
|
887
|
+
end
|
888
|
+
|
889
|
+
context 'serial_no orderable' do
|
890
|
+
|
891
|
+
let(:serial_nos){ MultipleColumnsOrderable.all.map(&:serial_no).sort }
|
892
|
+
|
893
|
+
it 'should have proper serial_no column' do
|
894
|
+
expect(MultipleColumnsOrderable.fields.key?('serial_no')).to be true
|
895
|
+
expect(MultipleColumnsOrderable.fields['serial_no'].options[:type]).to eq(Integer)
|
896
|
+
end
|
897
|
+
|
898
|
+
it 'should have index on serial_no column' do
|
899
|
+
if MongoidOrderable.mongoid2?
|
900
|
+
expect(MultipleColumnsOrderable.index_options[[[:serial_no, 1]]]).not_to be_nil
|
901
|
+
elsif MongoidOrderable.mongoid3?
|
902
|
+
expect(MultipleColumnsOrderable.index_options[{:serial_no => 1}]).not_to be_nil
|
903
|
+
else
|
904
|
+
expect(MultipleColumnsOrderable.index_specifications.detect { |spec| spec.key == {:serial_no => 1} }).not_to be_nil
|
905
|
+
end
|
906
|
+
end
|
907
|
+
|
908
|
+
it 'should have a orderable base of 1' do
|
909
|
+
expect(MultipleColumnsOrderable.first.orderable_base(:serial_no)).to eq(1)
|
910
|
+
end
|
911
|
+
|
912
|
+
it 'should set proper position while creation' do
|
913
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
914
|
+
end
|
915
|
+
|
916
|
+
describe 'removement' do
|
917
|
+
|
918
|
+
it 'top' do
|
919
|
+
MultipleColumnsOrderable.where(:serial_no => 1).destroy
|
920
|
+
expect(serial_nos).to eq([1, 2, 3, 4])
|
921
|
+
end
|
922
|
+
|
923
|
+
it 'bottom' do
|
924
|
+
MultipleColumnsOrderable.where(:serial_no => 5).destroy
|
925
|
+
expect(serial_nos).to eq([1, 2, 3, 4])
|
926
|
+
end
|
927
|
+
|
928
|
+
it 'middle' do
|
929
|
+
MultipleColumnsOrderable.where(:serial_no => 3).destroy
|
930
|
+
expect(serial_nos).to eq([1, 2, 3, 4])
|
931
|
+
end
|
932
|
+
end
|
933
|
+
|
934
|
+
describe 'inserting' do
|
935
|
+
let(:newbie){ MultipleColumnsOrderable.create! }
|
936
|
+
|
937
|
+
before { @position = newbie.position }
|
938
|
+
|
939
|
+
it 'top' do
|
940
|
+
newbie.move_serial_no_to! :top
|
941
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5, 6])
|
942
|
+
expect(newbie.serial_no).to eq(1)
|
943
|
+
expect(newbie.position).to eq(@position)
|
944
|
+
end
|
945
|
+
|
946
|
+
it 'bottom' do
|
947
|
+
newbie.move_serial_no_to! :bottom
|
948
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5, 6])
|
949
|
+
expect(newbie.serial_no).to eq(6)
|
950
|
+
expect(newbie.position).to eq(@position)
|
951
|
+
end
|
952
|
+
|
953
|
+
it 'middle' do
|
954
|
+
newbie.move_serial_no_to! 4
|
955
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5, 6])
|
956
|
+
expect(newbie.serial_no).to eq(4)
|
957
|
+
expect(newbie.position).to eq(@position)
|
958
|
+
end
|
959
|
+
end
|
960
|
+
|
961
|
+
describe 'movement' do
|
962
|
+
it 'higher from top' do
|
963
|
+
record = MultipleColumnsOrderable.where(:serial_no => 1).first
|
964
|
+
position = record.position
|
965
|
+
record.move_serial_no_higher!
|
966
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
967
|
+
expect(record.serial_no).to eq(1)
|
968
|
+
expect(record.position).to eq(position)
|
969
|
+
end
|
970
|
+
|
971
|
+
it 'higher from bottom' do
|
972
|
+
record = MultipleColumnsOrderable.where(:serial_no => 5).first
|
973
|
+
position = record.position
|
974
|
+
record.move_serial_no_higher!
|
975
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
976
|
+
expect(record.serial_no).to eq(4)
|
977
|
+
expect(record.position).to eq(position)
|
978
|
+
end
|
979
|
+
|
980
|
+
it 'higher from middle' do
|
981
|
+
record = MultipleColumnsOrderable.where(:serial_no => 3).first
|
982
|
+
position = record.position
|
983
|
+
record.move_serial_no_higher!
|
984
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
985
|
+
expect(record.serial_no).to eq(2)
|
986
|
+
expect(record.position).to eq(position)
|
987
|
+
end
|
988
|
+
|
989
|
+
it 'lower from top' do
|
990
|
+
record = MultipleColumnsOrderable.where(:serial_no => 1).first
|
991
|
+
position = record.position
|
992
|
+
record.move_serial_no_lower!
|
993
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
994
|
+
expect(record.serial_no).to eq(2)
|
995
|
+
expect(record.position).to eq(position)
|
996
|
+
end
|
997
|
+
|
998
|
+
it 'lower from bottom' do
|
999
|
+
record = MultipleColumnsOrderable.where(:serial_no => 5).first
|
1000
|
+
position = record.position
|
1001
|
+
record.move_serial_no_lower!
|
1002
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
1003
|
+
expect(record.serial_no).to eq(5)
|
1004
|
+
expect(record.position).to eq(position)
|
1005
|
+
end
|
1006
|
+
|
1007
|
+
it 'lower from middle' do
|
1008
|
+
record = MultipleColumnsOrderable.where(:serial_no => 3).first
|
1009
|
+
position = record.position
|
1010
|
+
record.move_serial_no_lower!
|
1011
|
+
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
1012
|
+
expect(record.serial_no).to eq(4)
|
1013
|
+
expect(record.position).to eq(position)
|
1014
|
+
end
|
1015
|
+
end
|
1016
|
+
|
1017
|
+
describe 'utility methods' do
|
1018
|
+
|
1019
|
+
before do
|
1020
|
+
@record_1 = MultipleColumnsOrderable.where(:serial_no => 1).first
|
1021
|
+
@record_2 = MultipleColumnsOrderable.where(:serial_no => 2).first
|
1022
|
+
@record_3 = MultipleColumnsOrderable.where(:serial_no => 3).first
|
1023
|
+
@record_4 = MultipleColumnsOrderable.where(:serial_no => 4).first
|
1024
|
+
@record_5 = MultipleColumnsOrderable.where(:serial_no => 5).first
|
1025
|
+
end
|
1026
|
+
|
1027
|
+
it "should return the lower/higher item on the list for next_item/previous_item" do
|
1028
|
+
expect(@record_1.next_serial_no_item).to eq(@record_2)
|
1029
|
+
expect(@record_3.next_serial_no_item).to eq(@record_4)
|
1030
|
+
expect(@record_5.next_serial_no_item).to eq(nil)
|
1031
|
+
expect(@record_1.prev_serial_no_item).to eq(nil)
|
1032
|
+
expect(@record_3.prev_serial_no_item).to eq(@record_2)
|
1033
|
+
expect(@record_5.prev_serial_no_item).to eq(@record_4)
|
1034
|
+
end
|
1035
|
+
|
1036
|
+
it "should return a collection of items lower/higher on the list for next_items/previous_items" do
|
1037
|
+
expect(@record_1.next_serial_no_items.to_a).to eq([@record_2, @record_3, @record_4, @record_5])
|
1038
|
+
expect(@record_3.next_serial_no_items.to_a).to eq([@record_4, @record_5])
|
1039
|
+
expect(@record_5.next_serial_no_items.to_a).to eq([])
|
1040
|
+
expect(@record_1.previous_serial_no_items.to_a).to eq([])
|
1041
|
+
expect(@record_3.previous_serial_no_items.to_a).to eq([@record_1, @record_2])
|
1042
|
+
expect(@record_5.previous_serial_no_items.to_a).to eq([@record_1, @record_2, @record_3, @record_4])
|
1043
|
+
end
|
1044
|
+
end
|
1045
|
+
|
1046
|
+
end
|
1047
|
+
|
1048
|
+
context 'position orderable' do
|
1049
|
+
|
1050
|
+
let(:positions){ MultipleColumnsOrderable.all.map(&:position).sort }
|
1051
|
+
|
1052
|
+
it 'should not have default position field' do
|
1053
|
+
expect(MultipleColumnsOrderable.fields).not_to have_key('position')
|
1054
|
+
end
|
1055
|
+
|
1056
|
+
it 'should have custom pos field' do
|
1057
|
+
expect(MultipleColumnsOrderable.fields).to have_key('pos')
|
1058
|
+
expect(MultipleColumnsOrderable.fields['pos'].options[:type]).to eq(Integer)
|
1059
|
+
end
|
1060
|
+
|
1061
|
+
it 'should have index on position column' do
|
1062
|
+
if MongoidOrderable.mongoid2?
|
1063
|
+
expect(MultipleColumnsOrderable.index_options[[[:position, 1]]]).to be_nil
|
1064
|
+
elsif MongoidOrderable.mongoid3?
|
1065
|
+
expect(MultipleColumnsOrderable.index_options[{:position => 1}]).to be_nil
|
1066
|
+
else
|
1067
|
+
expect(MultipleColumnsOrderable.index_specifications.detect { |spec| spec.key == {:position => 1} }).to be_nil
|
1068
|
+
end
|
1069
|
+
end
|
1070
|
+
|
1071
|
+
it 'should have a orderable base of 0' do
|
1072
|
+
expect(MultipleColumnsOrderable.first.orderable_base(:position)).to eq(0)
|
1073
|
+
end
|
1074
|
+
|
1075
|
+
it 'should set proper position while creation' do
|
1076
|
+
expect(positions).to eq([0, 1, 2, 3, 4])
|
1077
|
+
end
|
1078
|
+
|
1079
|
+
describe 'removement' do
|
1080
|
+
|
1081
|
+
it 'top' do
|
1082
|
+
MultipleColumnsOrderable.where(:pos => 1).destroy
|
1083
|
+
expect(positions).to eq([0, 1, 2, 3])
|
1084
|
+
end
|
1085
|
+
|
1086
|
+
it 'bottom' do
|
1087
|
+
MultipleColumnsOrderable.where(:pos => 4).destroy
|
1088
|
+
expect(positions).to eq([0, 1, 2, 3])
|
1089
|
+
end
|
1090
|
+
|
1091
|
+
it 'middle' do
|
1092
|
+
MultipleColumnsOrderable.where(:pos => 3).destroy
|
1093
|
+
expect(positions).to eq([0, 1, 2, 3])
|
1094
|
+
end
|
1095
|
+
end
|
1096
|
+
|
1097
|
+
describe 'inserting' do
|
1098
|
+
let(:newbie){ MultipleColumnsOrderable.create! }
|
1099
|
+
|
1100
|
+
before { @serial_no = newbie.serial_no }
|
1101
|
+
|
1102
|
+
it 'top' do
|
1103
|
+
newbie.move_position_to! :top
|
1104
|
+
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
1105
|
+
expect(newbie.position).to eq(0)
|
1106
|
+
expect(newbie.serial_no).to eq(@serial_no)
|
1107
|
+
end
|
1108
|
+
|
1109
|
+
it 'bottom' do
|
1110
|
+
newbie.move_position_to! :bottom
|
1111
|
+
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
1112
|
+
expect(newbie.position).to eq(5)
|
1113
|
+
expect(newbie.serial_no).to eq(@serial_no)
|
1114
|
+
end
|
1115
|
+
|
1116
|
+
it 'middle' do
|
1117
|
+
newbie.move_position_to! 4
|
1118
|
+
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
1119
|
+
expect(newbie.position).to eq(4)
|
1120
|
+
expect(newbie.serial_no).to eq(@serial_no)
|
1121
|
+
end
|
1122
|
+
end
|
1123
|
+
|
1124
|
+
describe 'movement' do
|
1125
|
+
it 'higher from top' do
|
1126
|
+
record = MultipleColumnsOrderable.where(:pos => 0).first
|
1127
|
+
position = record.serial_no
|
1128
|
+
record.move_position_higher!
|
1129
|
+
expect(positions).to eq([0, 1, 2, 3, 4])
|
1130
|
+
expect(record.position).to eq(0)
|
1131
|
+
expect(record.serial_no).to eq(position)
|
1132
|
+
end
|
1133
|
+
|
1134
|
+
it 'higher from bottom' do
|
1135
|
+
record = MultipleColumnsOrderable.where(:pos => 4).first
|
1136
|
+
position = record.serial_no
|
1137
|
+
record.move_position_higher!
|
1138
|
+
expect(positions).to eq([0, 1, 2, 3, 4])
|
1139
|
+
expect(record.position).to eq(3)
|
1140
|
+
expect(record.serial_no).to eq(position)
|
1141
|
+
end
|
1142
|
+
|
1143
|
+
it 'higher from middle' do
|
1144
|
+
record = MultipleColumnsOrderable.where(:pos => 3).first
|
1145
|
+
position = record.serial_no
|
1146
|
+
record.move_position_higher!
|
1147
|
+
expect(positions).to eq([0, 1, 2, 3, 4])
|
1148
|
+
expect(record.position).to eq(2)
|
1149
|
+
expect(record.serial_no).to eq(position)
|
1150
|
+
end
|
1151
|
+
|
1152
|
+
it 'lower from top' do
|
1153
|
+
record = MultipleColumnsOrderable.where(:pos => 0).first
|
1154
|
+
position = record.serial_no
|
1155
|
+
record.move_position_lower!
|
1156
|
+
expect(positions).to eq([0, 1, 2, 3, 4])
|
1157
|
+
expect(record.position).to eq(1)
|
1158
|
+
expect(record.serial_no).to eq(position)
|
1159
|
+
end
|
1160
|
+
|
1161
|
+
it 'lower from bottom' do
|
1162
|
+
record = MultipleColumnsOrderable.where(:pos => 4).first
|
1163
|
+
position = record.serial_no
|
1164
|
+
record.move_position_lower!
|
1165
|
+
expect(positions).to eq([0, 1, 2, 3, 4])
|
1166
|
+
expect(record.position).to eq(4)
|
1167
|
+
expect(record.serial_no).to eq(position)
|
1168
|
+
end
|
1169
|
+
|
1170
|
+
it 'lower from middle' do
|
1171
|
+
record = MultipleColumnsOrderable.where(:pos => 3).first
|
1172
|
+
position = record.serial_no
|
1173
|
+
record.move_position_lower!
|
1174
|
+
expect(positions).to eq([0, 1, 2, 3, 4])
|
1175
|
+
expect(record.position).to eq(4)
|
1176
|
+
expect(record.serial_no).to eq(position)
|
1177
|
+
end
|
1178
|
+
end
|
1179
|
+
|
1180
|
+
describe 'utility methods' do
|
1181
|
+
|
1182
|
+
before do
|
1183
|
+
@record_1 = MultipleColumnsOrderable.where(:pos => 0).first
|
1184
|
+
@record_2 = MultipleColumnsOrderable.where(:pos => 1).first
|
1185
|
+
@record_3 = MultipleColumnsOrderable.where(:pos => 2).first
|
1186
|
+
@record_4 = MultipleColumnsOrderable.where(:pos => 3).first
|
1187
|
+
@record_5 = MultipleColumnsOrderable.where(:pos => 4).first
|
1188
|
+
end
|
1189
|
+
|
1190
|
+
it "should return the lower/higher item on the list for next_item/previous_item" do
|
1191
|
+
expect(@record_1.next_position_item).to eq(@record_2)
|
1192
|
+
expect(@record_3.next_position_item).to eq(@record_4)
|
1193
|
+
expect(@record_5.next_position_item).to eq(nil)
|
1194
|
+
expect(@record_1.prev_position_item).to eq(nil)
|
1195
|
+
expect(@record_3.prev_position_item).to eq(@record_2)
|
1196
|
+
expect(@record_5.prev_position_item).to eq(@record_4)
|
1197
|
+
end
|
1198
|
+
|
1199
|
+
it "should return a collection of items lower/higher on the list for next_items/previous_items" do
|
1200
|
+
expect(@record_1.next_position_items.to_a).to eq([@record_2, @record_3, @record_4, @record_5])
|
1201
|
+
expect(@record_3.next_position_items.to_a).to eq([@record_4, @record_5])
|
1202
|
+
expect(@record_5.next_position_items.to_a).to eq([])
|
1203
|
+
expect(@record_1.previous_position_items.to_a).to eq([])
|
1204
|
+
expect(@record_3.previous_position_items.to_a).to eq([@record_1, @record_2])
|
1205
|
+
expect(@record_5.previous_position_items.to_a).to eq([@record_1, @record_2, @record_3, @record_4])
|
1206
|
+
end
|
1207
|
+
end
|
1208
|
+
|
1209
|
+
end
|
1210
|
+
|
1211
|
+
context 'group_count orderable' do
|
1212
|
+
before :each do
|
1213
|
+
MultipleColumnsOrderable.delete_all
|
1214
|
+
2.times { MultipleColumnsOrderable.create! :group_id => 1 }
|
1215
|
+
3.times { MultipleColumnsOrderable.create! :group_id => 2 }
|
1216
|
+
end
|
1217
|
+
|
1218
|
+
let(:all_groups){ MultipleColumnsOrderable.order_by([:group_id, :asc], [:groups, :asc]).map(&:groups) }
|
1219
|
+
|
1220
|
+
it 'should set proper position while creation' do
|
1221
|
+
expect(all_groups).to eq([1, 2, 1, 2, 3])
|
1222
|
+
end
|
1223
|
+
|
1224
|
+
describe 'removement' do
|
1225
|
+
|
1226
|
+
it 'top' do
|
1227
|
+
MultipleColumnsOrderable.where(:groups => 1, :group_id => 1).destroy
|
1228
|
+
expect(all_groups).to eq([1, 1, 2, 3])
|
1229
|
+
end
|
1230
|
+
|
1231
|
+
it 'bottom' do
|
1232
|
+
MultipleColumnsOrderable.where(:groups => 3, :group_id => 2).destroy
|
1233
|
+
expect(all_groups).to eq([1, 2, 1, 2])
|
1234
|
+
end
|
1235
|
+
|
1236
|
+
it 'middle' do
|
1237
|
+
MultipleColumnsOrderable.where(:groups => 2, :group_id => 2).destroy
|
1238
|
+
expect(all_groups).to eq([1, 2, 1, 2])
|
1239
|
+
end
|
1240
|
+
end
|
1241
|
+
|
1242
|
+
describe 'inserting' do
|
1243
|
+
|
1244
|
+
it 'top' do
|
1245
|
+
newbie = MultipleColumnsOrderable.create! :group_id => 1
|
1246
|
+
newbie.move_groups_to! :top
|
1247
|
+
expect(all_groups).to eq([1, 2, 3, 1, 2, 3])
|
1248
|
+
expect(newbie.groups).to eq(1)
|
1249
|
+
end
|
1250
|
+
|
1251
|
+
it 'bottom' do
|
1252
|
+
newbie = MultipleColumnsOrderable.create! :group_id => 2
|
1253
|
+
newbie.move_groups_to! :bottom
|
1254
|
+
expect(all_groups).to eq([1, 2, 1, 2, 3, 4])
|
1255
|
+
expect(newbie.groups).to eq(4)
|
1256
|
+
end
|
1257
|
+
|
1258
|
+
it 'middle' do
|
1259
|
+
newbie = MultipleColumnsOrderable.create! :group_id => 2
|
1260
|
+
newbie.move_groups_to! 2
|
1261
|
+
expect(all_groups).to eq([1, 2, 1, 2, 3, 4])
|
1262
|
+
expect(newbie.groups).to eq(2)
|
1263
|
+
end
|
1264
|
+
end
|
1265
|
+
|
1266
|
+
describe 'scope movement' do
|
1267
|
+
|
1268
|
+
let(:record){ MultipleColumnsOrderable.where(:group_id => 2, :groups => 2).first }
|
1269
|
+
|
1270
|
+
it 'to a new scope group' do
|
1271
|
+
record.update_attributes :group_id => 3
|
1272
|
+
expect(all_groups).to eq([1, 2, 1, 2, 1])
|
1273
|
+
expect(record.groups).to eq(1)
|
1274
|
+
end
|
1275
|
+
|
1276
|
+
context 'when moving to an existing scope group' do
|
1277
|
+
|
1278
|
+
it 'without a position' do
|
1279
|
+
record.update_attributes :group_id => 1
|
1280
|
+
expect(all_groups).to eq([1, 2, 3, 1, 2])
|
1281
|
+
expect(record.reload.groups).to eq(3)
|
1282
|
+
end
|
1283
|
+
|
1284
|
+
it 'with symbol position' do
|
1285
|
+
record.update_attributes :group_id => 1
|
1286
|
+
record.move_groups_to! :top
|
1287
|
+
expect(all_groups).to eq([1, 2, 3, 1, 2])
|
1288
|
+
expect(record.reload.groups).to eq(1)
|
1289
|
+
end
|
1290
|
+
|
1291
|
+
it 'with point position' do
|
1292
|
+
record.update_attributes :group_id => 1
|
1293
|
+
record.move_groups_to! 2
|
1294
|
+
expect(all_groups).to eq([1, 2, 3, 1, 2])
|
1295
|
+
expect(record.reload.groups).to eq(2)
|
1296
|
+
end
|
1297
|
+
end
|
1298
|
+
end
|
1299
|
+
|
1300
|
+
if defined?(Mongoid::IdentityMap)
|
1301
|
+
|
1302
|
+
context 'when identity map is enabled' do
|
1303
|
+
|
1304
|
+
let(:record){ MultipleColumnsOrderable.where(:group_id => 2, :groups => 2).first }
|
1305
|
+
|
1306
|
+
before do
|
1307
|
+
Mongoid.identity_map_enabled = true
|
1308
|
+
Mongoid::IdentityMap[MultipleColumnsOrderable.collection_name] = { record.id => record }
|
1309
|
+
end
|
1310
|
+
|
1311
|
+
after { Mongoid.identity_map_enabled = false }
|
1312
|
+
|
1313
|
+
it 'to a new scope group' do
|
1314
|
+
record.update_attributes :group_id => 3
|
1315
|
+
expect(all_groups).to eq([1, 2, 1, 2, 1])
|
1316
|
+
expect(record.groups).to eq(1)
|
1317
|
+
end
|
1318
|
+
|
1319
|
+
it 'to an existing scope group' do
|
1320
|
+
record.update_attributes :group_id => 1
|
1321
|
+
record.move_groups_to! 2
|
1322
|
+
expect(all_groups).to eq([1, 2, 3, 1, 2])
|
1323
|
+
expect(record.groups).to eq(2)
|
1324
|
+
end
|
1325
|
+
end
|
1326
|
+
end
|
1327
|
+
|
1328
|
+
describe 'utility methods' do
|
1329
|
+
|
1330
|
+
before do
|
1331
|
+
@record_1 = MultipleColumnsOrderable.where(:group_id => 2, :groups => 1).first
|
1332
|
+
@record_2 = MultipleColumnsOrderable.where(:group_id => 2, :groups => 2).first
|
1333
|
+
@record_3 = MultipleColumnsOrderable.where(:group_id => 2, :groups => 3).first
|
1334
|
+
@record_4 = MultipleColumnsOrderable.where(:group_id => 1, :groups => 1).first
|
1335
|
+
@record_5 = MultipleColumnsOrderable.where(:group_id => 1, :groups => 2).first
|
1336
|
+
end
|
1337
|
+
|
1338
|
+
it "should return the lower/higher item on the list for next_item/previous_item" do
|
1339
|
+
expect(@record_1.next_groups_item).to eq(@record_2)
|
1340
|
+
expect(@record_4.next_groups_item).to eq(@record_5)
|
1341
|
+
expect(@record_3.next_groups_item).to eq(nil)
|
1342
|
+
expect(@record_1.prev_groups_item).to eq(nil)
|
1343
|
+
expect(@record_3.prev_groups_item).to eq(@record_2)
|
1344
|
+
expect(@record_5.prev_groups_item).to eq(@record_4)
|
1345
|
+
end
|
1346
|
+
|
1347
|
+
it "should return a collection of items lower/higher on the list for next_items/previous_items" do
|
1348
|
+
expect(@record_1.next_groups_items.to_a).to eq([@record_2, @record_3])
|
1349
|
+
expect(@record_3.next_groups_items.to_a).to eq([])
|
1350
|
+
expect(@record_4.next_groups_items.to_a).to eq([@record_5])
|
1351
|
+
expect(@record_1.previous_groups_items.to_a).to eq([])
|
1352
|
+
expect(@record_3.previous_groups_items.to_a).to eq([@record_1, @record_2])
|
1353
|
+
expect(@record_5.previous_groups_items.to_a).to eq([@record_4])
|
1354
|
+
end
|
1355
|
+
end
|
1356
|
+
end
|
1357
|
+
end
|
1358
|
+
|
1359
|
+
describe MultipleScopedOrderable do
|
1360
|
+
before :each do
|
1361
|
+
Apple.delete_all; Orange.delete_all;
|
1362
|
+
MultipleScopedOrderable.delete_all
|
1363
|
+
|
1364
|
+
3.times do
|
1365
|
+
Apple.create; Orange.create
|
1366
|
+
end
|
1367
|
+
|
1368
|
+
MultipleScopedOrderable.create! :apple_id => 1, :orange_id => 1
|
1369
|
+
MultipleScopedOrderable.create! :apple_id => 2, :orange_id => 1
|
1370
|
+
MultipleScopedOrderable.create! :apple_id => 2, :orange_id => 2
|
1371
|
+
MultipleScopedOrderable.create! :apple_id => 1, :orange_id => 3
|
1372
|
+
MultipleScopedOrderable.create! :apple_id => 1, :orange_id => 1
|
1373
|
+
MultipleScopedOrderable.create! :apple_id => 3, :orange_id => 3
|
1374
|
+
MultipleScopedOrderable.create! :apple_id => 2, :orange_id => 3
|
1375
|
+
MultipleScopedOrderable.create! :apple_id => 3, :orange_id => 2
|
1376
|
+
MultipleScopedOrderable.create! :apple_id => 1, :orange_id => 3
|
1377
|
+
end
|
1378
|
+
|
1379
|
+
def apple_positions
|
1380
|
+
MultipleScopedOrderable.order_by([:apple_id, :asc], [:posa, :asc]).map(&:posa)
|
1381
|
+
end
|
1382
|
+
|
1383
|
+
def orange_positions
|
1384
|
+
MultipleScopedOrderable.order_by([:orange_id, :asc], [:poso, :asc]).map(&:poso)
|
1385
|
+
end
|
1386
|
+
|
1387
|
+
describe 'default positions' do
|
1388
|
+
it { expect(apple_positions).to eq([1, 2, 3, 4, 1, 2, 3, 1, 2]) }
|
1389
|
+
it { expect(orange_positions).to eq([1, 2, 3, 1, 2, 1, 2, 3, 4]) }
|
1390
|
+
end
|
1391
|
+
|
1392
|
+
describe 'change the scope of the apple' do
|
1393
|
+
let(:record) { MultipleScopedOrderable.first }
|
1394
|
+
before do
|
1395
|
+
record.update_attribute(:apple_id, 2)
|
1396
|
+
end
|
1397
|
+
|
1398
|
+
it 'should properly set the apple positions' do
|
1399
|
+
expect(apple_positions).to eq([1, 2, 3, 1, 2, 3, 4, 1, 2])
|
1400
|
+
end
|
1401
|
+
|
1402
|
+
it 'should not affect the orange positions' do
|
1403
|
+
expect(orange_positions).to eq([1, 2, 3, 1, 2, 1, 2, 3, 4])
|
1404
|
+
end
|
1405
|
+
end
|
1406
|
+
end
|
1407
|
+
|
609
1408
|
end
|