mongoid_orderable 4.1.0 → 4.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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'
@@ -1,3 +1,3 @@
1
1
  module MongoidOrderable
2
- VERSION = '4.1.0'
2
+ VERSION = '4.1.1'
3
3
  end
@@ -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').should be_true
111
- SimpleOrderable.fields['position'].options[:type].should == Integer
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].should_not be_nil
141
+ expect(SimpleOrderable.index_options[[[:position, 1]]]).not_to be_nil
117
142
  elsif MongoidOrderable.mongoid3?
118
- SimpleOrderable.index_options[{:position => 1}].should_not be_nil
143
+ expect(SimpleOrderable.index_options[{:position => 1}]).not_to be_nil
119
144
  else
120
- SimpleOrderable.index_specifications.detect { |spec| spec.key == {:position => 1} }.should_not be_nil
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.should == 1
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.should == [1, 2, 3, 4, 5]
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.should == [1, 2, 3, 4]
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.should == [1, 2, 3, 4]
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.should == [1, 2, 3, 4]
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.should == [1, 2, 3, 4, 5, 6]
155
- newbie.position.should == 1
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.should == [1, 2, 3, 4, 5, 6]
161
- newbie.position.should == 6
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.should == [1, 2, 3, 4, 5, 6]
167
- newbie.position.should == 4
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.should == [1, 2, 3, 4, 5]
177
- record.reload.position.should == 1
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.should == [1, 2, 3, 4, 5]
184
- record.reload.position.should == 4
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.should == [1, 2, 3, 4, 5]
191
- record.reload.position.should == 2
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.should == [1, 2, 3, 4, 5]
198
- record.reload.position.should == 2
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.should == [1, 2, 3, 4, 5]
205
- record.reload.position.should == 5
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.should == [1, 2, 3, 4, 5]
212
- record.reload.position.should == 4
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.should == [1, 2, 3, 4, 5]
219
- record.reload.position.should == 3
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.should == [1, 2, 1, 2, 3]
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.should == [1, 1, 2, 3]
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.should == [1, 2, 1, 2]
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.should == [1, 2, 1, 2]
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.should == [1, 2, 3, 1, 2, 3]
282
- newbie.position.should == 1
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.should == [1, 2, 1, 2, 3, 4]
288
- newbie.position.should == 4
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.should == [1, 2, 1, 2, 3, 4]
294
- newbie.position.should == 2
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.should == [1, 2, 1, 2, 1]
305
- record.position.should == 1
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.should == [1, 2, 3, 1, 2]
313
- record.reload.position.should == 3
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.should == [1, 2, 3, 1, 2]
319
- record.reload.position.should == 1
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.should == [1, 2, 3, 1, 2]
325
- record.reload.position.should == 2
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.should == [1, 2, 1, 2, 1]
348
- record.position.should == 1
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.should == [1, 2, 3, 1, 2]
354
- record.reload.position.should == 2
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.should == [[1, 2], [1, 2, 3]]
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.should == 1
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.should_not have_key('position')
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.should have_key('pos')
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').should eq('pos')
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].should be_nil
539
+ expect(NoIndexOrderable.index_options[[[:position, 1]]]).to be_nil
444
540
  else
445
- NoIndexOrderable.index_specifications.detect { |spec| spec.key == :position }.should be_nil
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.should == 0
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.should == [0, 1, 2, 3, 4]
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.should == [0, 1, 2, 3]
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.should == [0, 1, 2, 3]
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.should == [0, 1, 2, 3]
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.should == [0, 1, 2, 3, 4, 5]
494
- newbie.position.should == 0
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.should == [0, 1, 2, 3, 4, 5]
500
- newbie.position.should == 5
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.should == [0, 1, 2, 3, 4, 5]
506
- newbie.position.should == 3
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.should == [0, 1, 2, 3, 4]
516
- record.reload.position.should == 0
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.should == [0, 1, 2, 3, 4]
523
- record.reload.position.should == 3
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.should == [0, 1, 2, 3, 4]
530
- record.reload.position.should == 2
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.should == [0, 1, 2, 3, 4]
537
- record.reload.position.should == 1
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.should == [0, 1, 2, 3, 4]
544
- record.reload.position.should == 4
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.should == [0, 1, 2, 3, 4]
551
- record.reload.position.should == 3
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.should == [0, 1, 2, 3, 4]
558
- record.reload.position.should == 3
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.should == 1
589
- fruit2.position.should == 2
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