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.
@@ -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