acts_as_silent_list 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/test/helper.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'active_record'
12
+ require "#{File.dirname(__FILE__)}/../init"
data/test/test_list.rb ADDED
@@ -0,0 +1,1405 @@
1
+ # NOTE: following now done in helper.rb (better Readability)
2
+ require 'helper.rb'
3
+
4
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
5
+
6
+ def setup_db
7
+ ActiveRecord::Schema.define(:version => 1) do
8
+ create_table :mixins do |t|
9
+ t.column :pos, :integer
10
+ t.column :parent_id, :integer
11
+ t.column :parent_type, :string
12
+ t.column :created_at, :datetime
13
+ t.column :updated_at, :datetime
14
+ end
15
+ end
16
+ end
17
+
18
+ def setup_db_with_default
19
+ ActiveRecord::Schema.define(:version => 1) do
20
+ create_table :mixins do |t|
21
+ t.column :pos, :integer, :default => 0
22
+ t.column :parent_id, :integer
23
+ t.column :parent_type, :string
24
+ t.column :created_at, :datetime
25
+ t.column :updated_at, :datetime
26
+ end
27
+ end
28
+ end
29
+
30
+ # Returns true if ActiveRecord is rails3 version
31
+ def rails_3
32
+ defined?(ActiveRecord::VERSION) && ActiveRecord::VERSION::MAJOR >= 3
33
+ end
34
+
35
+ def teardown_db
36
+ ActiveRecord::Base.connection.tables.each do |table|
37
+ ActiveRecord::Base.connection.drop_table(table)
38
+ end
39
+ end
40
+
41
+ class Mixin < ActiveRecord::Base
42
+ end
43
+
44
+ class ListMixin < Mixin
45
+ acts_as_silent_list :column => "pos", :scope => :parent
46
+
47
+ def self.table_name() "mixins" end
48
+ end
49
+
50
+ class ListMixinSub1 < ListMixin
51
+ end
52
+
53
+ class ListMixinSub2 < ListMixin
54
+ end
55
+
56
+ class ListWithStringScopeMixin < ActiveRecord::Base
57
+ acts_as_silent_list :column => "pos", :scope => 'parent_id = #{parent_id}'
58
+
59
+ def self.table_name() "mixins" end
60
+ end
61
+
62
+ class ArrayScopeListMixin < Mixin
63
+ acts_as_silent_list :column => "pos", :scope => [:parent_id, :parent_type]
64
+
65
+ def self.table_name() "mixins" end
66
+ end
67
+
68
+ class ZeroBasedMixin < ActiveRecord::Base
69
+ acts_as_silent_list :column => "pos", :top_of_list => 0, :scope => [:parent_id]
70
+
71
+ def self.table_name() "mixins" end
72
+ end
73
+
74
+ class DefaultScopedMixin < ActiveRecord::Base
75
+ set_table_name 'mixins'
76
+ acts_as_silent_list :column => "pos"
77
+ if rails_3
78
+ default_scope order('pos ASC')
79
+ else
80
+ default_scope :order => 'pos ASC'
81
+ end
82
+ end
83
+
84
+ class CallbackMixin < ActiveRecord::Base
85
+ set_table_name 'mixins'
86
+ acts_as_silent_list :column => "pos"
87
+
88
+ before_save :store_before_save
89
+ after_save :store_after_save
90
+
91
+ attr_reader :after_save_called, :before_save_called
92
+
93
+ def store_after_save
94
+ $after_save_called = true
95
+ end
96
+
97
+ def store_before_save
98
+ $before_save_called = true
99
+ end
100
+ end
101
+
102
+ class ZeroBasedTest < Test::Unit::TestCase
103
+ def setup
104
+ setup_db
105
+ (1..4).each { |counter| ZeroBasedMixin.create! :pos => counter, :parent_id => 5 }
106
+ end
107
+
108
+ def teardown
109
+ teardown_db
110
+ end
111
+
112
+ def test_insert
113
+ new = ZeroBasedMixin.create(:parent_id => 20)
114
+ assert_equal 0, new.pos
115
+ assert new.first?
116
+ assert new.last?
117
+
118
+ new = ZeroBasedMixin.create(:parent_id => 20)
119
+ assert_equal 1, new.pos
120
+ assert !new.first?
121
+ assert new.last?
122
+
123
+ new = ZeroBasedMixin.create(:parent_id => 20)
124
+ assert_equal 2, new.pos
125
+ assert !new.first?
126
+ assert new.last?
127
+
128
+ new = ZeroBasedMixin.create(:parent_id => 0)
129
+ assert_equal 0, new.pos
130
+ assert new.first?
131
+ assert new.last?
132
+ end
133
+
134
+ def test_reordering
135
+ assert_equal [1, 2, 3, 4], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
136
+
137
+ ListMixin.find(2).move_lower
138
+ assert_equal [1, 3, 2, 4], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
139
+
140
+ ListMixin.find(2).move_higher
141
+ assert_equal [1, 2, 3, 4], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
142
+
143
+ ListMixin.find(1).move_to_bottom
144
+ assert_equal [2, 3, 4, 1], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
145
+
146
+ ListMixin.find(1).move_to_top
147
+ assert_equal [1, 2, 3, 4], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
148
+
149
+ ListMixin.find(2).move_to_bottom
150
+ assert_equal [1, 3, 4, 2], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
151
+
152
+ ListMixin.find(4).move_to_top
153
+ assert_equal [4, 1, 3, 2], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
154
+ end
155
+
156
+ def test_insert_at
157
+ new = ZeroBasedMixin.create(:parent_id => 20)
158
+ assert_equal 0, new.pos
159
+
160
+ new = ZeroBasedMixin.create(:parent_id => 20)
161
+ assert_equal 1, new.pos
162
+
163
+ new = ZeroBasedMixin.create(:parent_id => 20)
164
+ assert_equal 2, new.pos
165
+
166
+ new4 = ZeroBasedMixin.create(:parent_id => 20)
167
+ assert_equal 3, new4.pos
168
+
169
+ new4.insert_at(2)
170
+ assert_equal 2, new4.pos
171
+
172
+ new.reload
173
+ assert_equal 3, new.pos
174
+
175
+ new.insert_at(2)
176
+ assert_equal 2, new.pos
177
+
178
+ new4.reload
179
+ assert_equal 3, new4.pos
180
+
181
+ new5 = ListMixin.create(:parent_id => 20)
182
+ assert_equal 4, new5.pos
183
+
184
+ new5.insert_at(1)
185
+ assert_equal 1, new5.pos
186
+
187
+ new4.reload
188
+ assert_equal 4, new4.pos
189
+ end
190
+
191
+ end
192
+
193
+
194
+ class ListTest < Test::Unit::TestCase
195
+
196
+ def setup
197
+ setup_db
198
+ (1..4).each { |counter| ListMixin.create! :pos => counter, :parent_id => 5 }
199
+ end
200
+
201
+ def teardown
202
+ teardown_db
203
+ end
204
+
205
+ def test_reordering
206
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
207
+
208
+ ListMixin.find(2).move_lower
209
+ assert_equal [1, 3, 2, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
210
+
211
+ ListMixin.find(2).move_higher
212
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
213
+
214
+ ListMixin.find(1).move_to_bottom
215
+ assert_equal [2, 3, 4, 1], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
216
+
217
+ ListMixin.find(1).move_to_top
218
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
219
+
220
+ ListMixin.find(2).move_to_bottom
221
+ assert_equal [1, 3, 4, 2], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
222
+
223
+ ListMixin.find(4).move_to_top
224
+ assert_equal [4, 1, 3, 2], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
225
+ end
226
+
227
+ def test_move_to_bottom_with_next_to_last_item
228
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
229
+ ListMixin.find(3).move_to_bottom
230
+ assert_equal [1, 2, 4, 3], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
231
+ end
232
+
233
+ def test_next_prev
234
+ assert_equal ListMixin.find(2), ListMixin.find(1).lower_item
235
+ assert_nil ListMixin.find(1).higher_item
236
+ assert_equal ListMixin.find(3), ListMixin.find(4).higher_item
237
+ assert_nil ListMixin.find(4).lower_item
238
+ end
239
+
240
+ def test_injection
241
+ item = ListMixin.new(:parent_id => 1)
242
+ assert_equal '"mixins"."parent_id" = 1', item.scope_condition
243
+ assert_equal "pos", item.position_column
244
+ end
245
+
246
+ def test_insert
247
+ new = ListMixin.create(:parent_id => 20)
248
+ assert_equal 1, new.pos
249
+ assert new.first?
250
+ assert new.last?
251
+
252
+ new = ListMixin.create(:parent_id => 20)
253
+ assert_equal 2, new.pos
254
+ assert !new.first?
255
+ assert new.last?
256
+
257
+ new = ListMixin.create(:parent_id => 20)
258
+ assert_equal 3, new.pos
259
+ assert !new.first?
260
+ assert new.last?
261
+
262
+ new = ListMixin.create(:parent_id => 0)
263
+ assert_equal 1, new.pos
264
+ assert new.first?
265
+ assert new.last?
266
+ end
267
+
268
+ def test_insert_at
269
+ new = ListMixin.create(:parent_id => 20)
270
+ assert_equal 1, new.pos
271
+
272
+ new = ListMixin.create(:parent_id => 20)
273
+ assert_equal 2, new.pos
274
+
275
+ new = ListMixin.create(:parent_id => 20)
276
+ assert_equal 3, new.pos
277
+
278
+ new4 = ListMixin.create(:parent_id => 20)
279
+ assert_equal 4, new4.pos
280
+
281
+ new4.insert_at(3)
282
+ assert_equal 3, new4.pos
283
+
284
+ new.reload
285
+ assert_equal 4, new.pos
286
+
287
+ new.insert_at(2)
288
+ assert_equal 2, new.pos
289
+
290
+ new4.reload
291
+ assert_equal 4, new4.pos
292
+
293
+ new5 = ListMixin.create(:parent_id => 20)
294
+ assert_equal 5, new5.pos
295
+
296
+ new5.insert_at(1)
297
+ assert_equal 1, new5.pos
298
+
299
+ new4.reload
300
+ assert_equal 5, new4.pos
301
+ end
302
+
303
+ def test_delete_middle
304
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
305
+
306
+ ListMixin.find(2).destroy
307
+
308
+ assert_equal [1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
309
+
310
+ assert_equal 1, ListMixin.find(1).pos
311
+ assert_equal 2, ListMixin.find(3).pos
312
+ assert_equal 3, ListMixin.find(4).pos
313
+
314
+ ListMixin.find(1).destroy
315
+
316
+ assert_equal [3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
317
+
318
+ assert_equal 1, ListMixin.find(3).pos
319
+ assert_equal 2, ListMixin.find(4).pos
320
+ end
321
+
322
+ def test_with_string_based_scope
323
+ new = ListWithStringScopeMixin.create(:parent_id => 500)
324
+ assert_equal 1, new.pos
325
+ assert new.first?
326
+ assert new.last?
327
+ end
328
+
329
+ def test_nil_scope
330
+ new1, new2, new3 = ListMixin.create, ListMixin.create, ListMixin.create
331
+ new2.move_higher
332
+ assert_equal [new2, new1, new3], ListMixin.find(:all, :conditions => 'parent_id IS NULL', :order => 'pos')
333
+ end
334
+
335
+ def test_remove_from_list_should_then_fail_in_list?
336
+ assert_equal true, ListMixin.find(1).in_list?
337
+ ListMixin.find(1).remove_from_list
338
+ assert_equal false, ListMixin.find(1).in_list?
339
+ end
340
+
341
+ def test_remove_from_list_should_set_position_to_nil
342
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
343
+
344
+ ListMixin.find(2).remove_from_list
345
+
346
+ assert_equal [2, 1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
347
+
348
+ assert_equal 1, ListMixin.find(1).pos
349
+ assert_equal nil, ListMixin.find(2).pos
350
+ assert_equal 2, ListMixin.find(3).pos
351
+ assert_equal 3, ListMixin.find(4).pos
352
+ end
353
+
354
+ def test_remove_before_destroy_does_not_shift_lower_items_twice
355
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
356
+
357
+ ListMixin.find(2).remove_from_list
358
+ ListMixin.find(2).destroy
359
+
360
+ assert_equal [1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
361
+
362
+ assert_equal 1, ListMixin.find(1).pos
363
+ assert_equal 2, ListMixin.find(3).pos
364
+ assert_equal 3, ListMixin.find(4).pos
365
+ end
366
+
367
+ def test_before_destroy_callbacks_do_not_update_position_to_nil_before_deleting_the_record
368
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
369
+
370
+ # We need to trigger all the before_destroy callbacks without actually
371
+ # destroying the record so we can see the affect the callbacks have on
372
+ # the record.
373
+ # NOTE: Hotfix for rails3 ActiveRecord
374
+ list = ListMixin.find(2)
375
+ if list.respond_to?(:run_callbacks)
376
+ # Refactored to work according to Rails3 ActiveRSupport Callbacks <http://api.rubyonrails.org/classes/ActiveSupport/Callbacks.html>
377
+ list.run_callbacks :destroy, :before if rails_3
378
+ list.run_callbacks(:before_destroy) if !rails_3
379
+ else
380
+ list.send(:callback, :before_destroy)
381
+ end
382
+
383
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
384
+
385
+ assert_equal 1, ListMixin.find(1).pos
386
+ assert_equal 2, ListMixin.find(2).pos
387
+ assert_equal 2, ListMixin.find(3).pos
388
+ assert_equal 3, ListMixin.find(4).pos
389
+ end
390
+
391
+ def test_before_create_callback_adds_to_bottom
392
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
393
+
394
+ new = ListMixin.create(:parent_id => 5)
395
+ assert_equal 5, new.pos
396
+ assert !new.first?
397
+ assert new.last?
398
+
399
+ assert_equal [1, 2, 3, 4, 5], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
400
+ end
401
+
402
+ def test_before_create_callback_adds_to_given_position
403
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
404
+
405
+ new = ListMixin.create(:pos => 1, :parent_id => 5)
406
+ assert_equal 1, new.pos
407
+ assert new.first?
408
+ assert !new.last?
409
+
410
+ assert_equal [5, 1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
411
+
412
+ new = ListMixin.create(:pos => 3, :parent_id => 5)
413
+ assert_equal 3, new.pos
414
+ assert !new.first?
415
+ assert !new.last?
416
+
417
+ assert_equal [5, 1, 6, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
418
+ end
419
+ end
420
+
421
+ class ListSubTest < Test::Unit::TestCase
422
+
423
+ def setup
424
+ setup_db
425
+ (1..4).each { |i| ((i % 2 == 1) ? ListMixinSub1 : ListMixinSub2).create! :pos => i, :parent_id => 5000 }
426
+ end
427
+
428
+ def teardown
429
+ teardown_db
430
+ end
431
+
432
+ def test_reordering
433
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
434
+
435
+ ListMixin.find(2).move_lower
436
+ assert_equal [1, 3, 2, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
437
+
438
+ ListMixin.find(2).move_higher
439
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
440
+
441
+ ListMixin.find(1).move_to_bottom
442
+ assert_equal [2, 3, 4, 1], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
443
+
444
+ ListMixin.find(1).move_to_top
445
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
446
+
447
+ ListMixin.find(2).move_to_bottom
448
+ assert_equal [1, 3, 4, 2], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
449
+
450
+ ListMixin.find(4).move_to_top
451
+ assert_equal [4, 1, 3, 2], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
452
+ end
453
+
454
+ def test_move_to_bottom_with_next_to_last_item
455
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
456
+ ListMixin.find(3).move_to_bottom
457
+ assert_equal [1, 2, 4, 3], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
458
+ end
459
+
460
+ def test_next_prev
461
+ assert_equal ListMixin.find(2), ListMixin.find(1).lower_item
462
+ assert_nil ListMixin.find(1).higher_item
463
+ assert_equal ListMixin.find(3), ListMixin.find(4).higher_item
464
+ assert_nil ListMixin.find(4).lower_item
465
+ end
466
+
467
+ def test_injection
468
+ item = ListMixin.new("parent_id"=>1)
469
+ assert_equal '"mixins"."parent_id" = 1', item.scope_condition
470
+ assert_equal "pos", item.position_column
471
+ end
472
+
473
+ def test_insert_at
474
+ new = ListMixin.create("parent_id" => 20)
475
+ assert_equal 1, new.pos
476
+
477
+ new = ListMixinSub1.create("parent_id" => 20)
478
+ assert_equal 2, new.pos
479
+
480
+ new = ListMixinSub2.create("parent_id" => 20)
481
+ assert_equal 3, new.pos
482
+
483
+ new4 = ListMixin.create("parent_id" => 20)
484
+ assert_equal 4, new4.pos
485
+
486
+ new4.insert_at(3)
487
+ assert_equal 3, new4.pos
488
+
489
+ new.reload
490
+ assert_equal 4, new.pos
491
+
492
+ new.insert_at(2)
493
+ assert_equal 2, new.pos
494
+
495
+ new4.reload
496
+ assert_equal 4, new4.pos
497
+
498
+ new5 = ListMixinSub1.create("parent_id" => 20)
499
+ assert_equal 5, new5.pos
500
+
501
+ new5.insert_at(1)
502
+ assert_equal 1, new5.pos
503
+
504
+ new4.reload
505
+ assert_equal 5, new4.pos
506
+ end
507
+
508
+ def test_delete_middle
509
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
510
+
511
+ ListMixin.find(2).destroy
512
+
513
+ assert_equal [1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
514
+
515
+ assert_equal 1, ListMixin.find(1).pos
516
+ assert_equal 2, ListMixin.find(3).pos
517
+ assert_equal 3, ListMixin.find(4).pos
518
+
519
+ ListMixin.find(1).destroy
520
+
521
+ assert_equal [3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
522
+
523
+ assert_equal 1, ListMixin.find(3).pos
524
+ assert_equal 2, ListMixin.find(4).pos
525
+ end
526
+
527
+ end
528
+
529
+ class ArrayScopeListTest < Test::Unit::TestCase
530
+
531
+ def setup
532
+ setup_db
533
+ (1..4).each { |counter| ArrayScopeListMixin.create! :pos => counter, :parent_id => 5, :parent_type => 'ParentClass' }
534
+ end
535
+
536
+ def teardown
537
+ teardown_db
538
+ end
539
+
540
+ def test_reordering
541
+ assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
542
+
543
+ ArrayScopeListMixin.find(2).move_lower
544
+ assert_equal [1, 3, 2, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
545
+
546
+ ArrayScopeListMixin.find(2).move_higher
547
+ assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
548
+
549
+ ArrayScopeListMixin.find(1).move_to_bottom
550
+ assert_equal [2, 3, 4, 1], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
551
+
552
+ ArrayScopeListMixin.find(1).move_to_top
553
+ assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
554
+
555
+ ArrayScopeListMixin.find(2).move_to_bottom
556
+ assert_equal [1, 3, 4, 2], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
557
+
558
+ ArrayScopeListMixin.find(4).move_to_top
559
+ assert_equal [4, 1, 3, 2], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
560
+ end
561
+
562
+ def test_move_to_bottom_with_next_to_last_item
563
+ assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
564
+ ArrayScopeListMixin.find(3).move_to_bottom
565
+ assert_equal [1, 2, 4, 3], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
566
+ end
567
+
568
+ def test_next_prev
569
+ assert_equal ArrayScopeListMixin.find(2), ArrayScopeListMixin.find(1).lower_item
570
+ assert_nil ArrayScopeListMixin.find(1).higher_item
571
+ assert_equal ArrayScopeListMixin.find(3), ArrayScopeListMixin.find(4).higher_item
572
+ assert_nil ArrayScopeListMixin.find(4).lower_item
573
+ end
574
+
575
+ def test_injection
576
+ item = ArrayScopeListMixin.new(:parent_id => 1, :parent_type => 'ParentClass')
577
+ assert_equal '"mixins"."parent_id" = 1 AND "mixins"."parent_type" = \'ParentClass\'', item.scope_condition
578
+ assert_equal "pos", item.position_column
579
+ end
580
+
581
+ def test_insert
582
+ new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
583
+ assert_equal 1, new.pos
584
+ assert new.first?
585
+ assert new.last?
586
+
587
+ new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
588
+ assert_equal 2, new.pos
589
+ assert !new.first?
590
+ assert new.last?
591
+
592
+ new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
593
+ assert_equal 3, new.pos
594
+ assert !new.first?
595
+ assert new.last?
596
+
597
+ new = ArrayScopeListMixin.create(:parent_id => 0, :parent_type => 'ParentClass')
598
+ assert_equal 1, new.pos
599
+ assert new.first?
600
+ assert new.last?
601
+ end
602
+
603
+ def test_insert_at
604
+ new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
605
+ assert_equal 1, new.pos
606
+
607
+ new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
608
+ assert_equal 2, new.pos
609
+
610
+ new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
611
+ assert_equal 3, new.pos
612
+
613
+ new4 = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
614
+ assert_equal 4, new4.pos
615
+
616
+ new4.insert_at(3)
617
+ assert_equal 3, new4.pos
618
+
619
+ new.reload
620
+ assert_equal 4, new.pos
621
+
622
+ new.insert_at(2)
623
+ assert_equal 2, new.pos
624
+
625
+ new4.reload
626
+ assert_equal 4, new4.pos
627
+
628
+ new5 = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
629
+ assert_equal 5, new5.pos
630
+
631
+ new5.insert_at(1)
632
+ assert_equal 1, new5.pos
633
+
634
+ new4.reload
635
+ assert_equal 5, new4.pos
636
+ end
637
+
638
+ def test_delete_middle
639
+ assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
640
+
641
+ ArrayScopeListMixin.find(2).destroy
642
+
643
+ assert_equal [1, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
644
+
645
+ assert_equal 1, ArrayScopeListMixin.find(1).pos
646
+ assert_equal 2, ArrayScopeListMixin.find(3).pos
647
+ assert_equal 3, ArrayScopeListMixin.find(4).pos
648
+
649
+ ArrayScopeListMixin.find(1).destroy
650
+
651
+ assert_equal [3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
652
+
653
+ assert_equal 1, ArrayScopeListMixin.find(3).pos
654
+ assert_equal 2, ArrayScopeListMixin.find(4).pos
655
+ end
656
+
657
+ def test_remove_from_list_should_then_fail_in_list?
658
+ assert_equal true, ArrayScopeListMixin.find(1).in_list?
659
+ ArrayScopeListMixin.find(1).remove_from_list
660
+ assert_equal false, ArrayScopeListMixin.find(1).in_list?
661
+ end
662
+
663
+ def test_remove_from_list_should_set_position_to_nil
664
+ assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
665
+
666
+ ArrayScopeListMixin.find(2).remove_from_list
667
+
668
+ assert_equal [2, 1, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
669
+
670
+ assert_equal 1, ArrayScopeListMixin.find(1).pos
671
+ assert_equal nil, ArrayScopeListMixin.find(2).pos
672
+ assert_equal 2, ArrayScopeListMixin.find(3).pos
673
+ assert_equal 3, ArrayScopeListMixin.find(4).pos
674
+ end
675
+
676
+ def test_remove_before_destroy_does_not_shift_lower_items_twice
677
+ assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
678
+
679
+ ArrayScopeListMixin.find(2).remove_from_list
680
+ ArrayScopeListMixin.find(2).destroy
681
+
682
+ assert_equal [1, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
683
+
684
+ assert_equal 1, ArrayScopeListMixin.find(1).pos
685
+ assert_equal 2, ArrayScopeListMixin.find(3).pos
686
+ assert_equal 3, ArrayScopeListMixin.find(4).pos
687
+ end
688
+
689
+ end
690
+
691
+ class ZeroBasedTestWithDefault < Test::Unit::TestCase
692
+ def setup
693
+ setup_db_with_default
694
+ (1..4).each { |counter| ZeroBasedMixin.create! :pos => counter, :parent_id => 5 }
695
+ end
696
+
697
+ def teardown
698
+ teardown_db
699
+ end
700
+
701
+ def test_insert
702
+ new = ZeroBasedMixin.create(:parent_id => 20)
703
+ assert_equal 0, new.pos
704
+ assert new.first?
705
+ assert new.last?
706
+
707
+ new = ZeroBasedMixin.create(:parent_id => 20)
708
+ assert_equal 1, new.pos
709
+ assert !new.first?
710
+ assert new.last?
711
+
712
+ new = ZeroBasedMixin.create(:parent_id => 20)
713
+ assert_equal 2, new.pos
714
+ assert !new.first?
715
+ assert new.last?
716
+
717
+ new = ZeroBasedMixin.create(:parent_id => 0)
718
+ assert_equal 0, new.pos
719
+ assert new.first?
720
+ assert new.last?
721
+ end
722
+
723
+ def test_reordering
724
+ assert_equal [1, 2, 3, 4], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
725
+
726
+ ListMixin.find(2).move_lower
727
+ assert_equal [1, 3, 2, 4], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
728
+
729
+ ListMixin.find(2).move_higher
730
+ assert_equal [1, 2, 3, 4], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
731
+
732
+ ListMixin.find(1).move_to_bottom
733
+ assert_equal [2, 3, 4, 1], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
734
+
735
+ ListMixin.find(1).move_to_top
736
+ assert_equal [1, 2, 3, 4], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
737
+
738
+ ListMixin.find(2).move_to_bottom
739
+ assert_equal [1, 3, 4, 2], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
740
+
741
+ ListMixin.find(4).move_to_top
742
+ assert_equal [4, 1, 3, 2], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
743
+ end
744
+
745
+ def test_insert_at
746
+ new = ZeroBasedMixin.create(:parent_id => 20)
747
+ assert_equal 0, new.pos
748
+
749
+ new = ZeroBasedMixin.create(:parent_id => 20)
750
+ assert_equal 1, new.pos
751
+
752
+ new = ZeroBasedMixin.create(:parent_id => 20)
753
+ assert_equal 2, new.pos
754
+
755
+ new4 = ZeroBasedMixin.create(:parent_id => 20)
756
+ assert_equal 3, new4.pos
757
+
758
+ new4.insert_at(2)
759
+ assert_equal 2, new4.pos
760
+
761
+ new.reload
762
+ assert_equal 3, new.pos
763
+
764
+ new.insert_at(2)
765
+ assert_equal 2, new.pos
766
+
767
+ new4.reload
768
+ assert_equal 3, new4.pos
769
+
770
+ new5 = ListMixin.create(:parent_id => 20)
771
+ assert_equal 4, new5.pos
772
+
773
+ new5.insert_at(1)
774
+ assert_equal 1, new5.pos
775
+
776
+ new4.reload
777
+ assert_equal 4, new4.pos
778
+ end
779
+
780
+ end
781
+
782
+
783
+ class ListTestWithDefault < Test::Unit::TestCase
784
+
785
+ def setup
786
+ setup_db_with_default
787
+ (1..4).each { |counter| ListMixin.create! :pos => counter, :parent_id => 5 }
788
+ end
789
+
790
+ def teardown
791
+ teardown_db
792
+ end
793
+
794
+ def test_reordering
795
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
796
+
797
+ ListMixin.find(2).move_lower
798
+ assert_equal [1, 3, 2, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
799
+
800
+ ListMixin.find(2).move_higher
801
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
802
+
803
+ ListMixin.find(1).move_to_bottom
804
+ assert_equal [2, 3, 4, 1], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
805
+
806
+ ListMixin.find(1).move_to_top
807
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
808
+
809
+ ListMixin.find(2).move_to_bottom
810
+ assert_equal [1, 3, 4, 2], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
811
+
812
+ ListMixin.find(4).move_to_top
813
+ assert_equal [4, 1, 3, 2], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
814
+ end
815
+
816
+ def test_move_to_bottom_with_next_to_last_item
817
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
818
+ ListMixin.find(3).move_to_bottom
819
+ assert_equal [1, 2, 4, 3], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
820
+ end
821
+
822
+ def test_next_prev
823
+ assert_equal ListMixin.find(2), ListMixin.find(1).lower_item
824
+ assert_nil ListMixin.find(1).higher_item
825
+ assert_equal ListMixin.find(3), ListMixin.find(4).higher_item
826
+ assert_nil ListMixin.find(4).lower_item
827
+ end
828
+
829
+ def test_injection
830
+ item = ListMixin.new(:parent_id => 1)
831
+ assert_equal '"mixins"."parent_id" = 1', item.scope_condition
832
+ assert_equal "pos", item.position_column
833
+ end
834
+
835
+ def test_insert
836
+ new = ListMixin.create(:parent_id => 20)
837
+ assert_equal 1, new.pos
838
+ assert new.first?
839
+ assert new.last?
840
+
841
+ new = ListMixin.create(:parent_id => 20)
842
+ assert_equal 2, new.pos
843
+ assert !new.first?
844
+ assert new.last?
845
+
846
+ new = ListMixin.create(:parent_id => 20)
847
+ assert_equal 3, new.pos
848
+ assert !new.first?
849
+ assert new.last?
850
+
851
+ new = ListMixin.create(:parent_id => 0)
852
+ assert_equal 1, new.pos
853
+ assert new.first?
854
+ assert new.last?
855
+ end
856
+
857
+ def test_insert_at
858
+ new = ListMixin.create(:parent_id => 20)
859
+ assert_equal 1, new.pos
860
+
861
+ new = ListMixin.create(:parent_id => 20)
862
+ assert_equal 2, new.pos
863
+
864
+ new = ListMixin.create(:parent_id => 20)
865
+ assert_equal 3, new.pos
866
+
867
+ new4 = ListMixin.create(:parent_id => 20)
868
+ assert_equal 4, new4.pos
869
+
870
+ new4.insert_at(3)
871
+ assert_equal 3, new4.pos
872
+
873
+ new.reload
874
+ assert_equal 4, new.pos
875
+
876
+ new.insert_at(2)
877
+ assert_equal 2, new.pos
878
+
879
+ new4.reload
880
+ assert_equal 4, new4.pos
881
+
882
+ new5 = ListMixin.create(:parent_id => 20)
883
+ assert_equal 5, new5.pos
884
+
885
+ new5.insert_at(1)
886
+ assert_equal 1, new5.pos
887
+
888
+ new4.reload
889
+ assert_equal 5, new4.pos
890
+ end
891
+
892
+ def test_delete_middle
893
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
894
+
895
+ ListMixin.find(2).destroy
896
+
897
+ assert_equal [1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
898
+
899
+ assert_equal 1, ListMixin.find(1).pos
900
+ assert_equal 2, ListMixin.find(3).pos
901
+ assert_equal 3, ListMixin.find(4).pos
902
+
903
+ ListMixin.find(1).destroy
904
+
905
+ assert_equal [3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
906
+
907
+ assert_equal 1, ListMixin.find(3).pos
908
+ assert_equal 2, ListMixin.find(4).pos
909
+ end
910
+
911
+ def test_with_string_based_scope
912
+ new = ListWithStringScopeMixin.create(:parent_id => 500)
913
+ assert_equal 1, new.pos
914
+ assert new.first?
915
+ assert new.last?
916
+ end
917
+
918
+ def test_nil_scope
919
+ new1, new2, new3 = ListMixin.create, ListMixin.create, ListMixin.create
920
+ new2.move_higher
921
+ assert_equal [new2, new1, new3], ListMixin.find(:all, :conditions => 'parent_id IS NULL', :order => 'pos')
922
+ end
923
+
924
+ def test_remove_from_list_should_then_fail_in_list?
925
+ assert_equal true, ListMixin.find(1).in_list?
926
+ ListMixin.find(1).remove_from_list
927
+ assert_equal false, ListMixin.find(1).in_list?
928
+ end
929
+
930
+ def test_remove_from_list_should_set_position_to_nil
931
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
932
+
933
+ ListMixin.find(2).remove_from_list
934
+
935
+ assert_equal [2, 1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
936
+
937
+ assert_equal 1, ListMixin.find(1).pos
938
+ assert_equal nil, ListMixin.find(2).pos
939
+ assert_equal 2, ListMixin.find(3).pos
940
+ assert_equal 3, ListMixin.find(4).pos
941
+ end
942
+
943
+ def test_remove_before_destroy_does_not_shift_lower_items_twice
944
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
945
+
946
+ ListMixin.find(2).remove_from_list
947
+ ListMixin.find(2).destroy
948
+
949
+ assert_equal [1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
950
+
951
+ assert_equal 1, ListMixin.find(1).pos
952
+ assert_equal 2, ListMixin.find(3).pos
953
+ assert_equal 3, ListMixin.find(4).pos
954
+ end
955
+
956
+ def test_before_destroy_callbacks_do_not_update_position_to_nil_before_deleting_the_record
957
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
958
+
959
+ # We need to trigger all the before_destroy callbacks without actually
960
+ # destroying the record so we can see the affect the callbacks have on
961
+ # the record.
962
+ # NOTE: Hotfix for rails3 ActiveRecord
963
+ list = ListMixin.find(2)
964
+ if list.respond_to?(:run_callbacks)
965
+ # Refactored to work according to Rails3 ActiveRSupport Callbacks <http://api.rubyonrails.org/classes/ActiveSupport/Callbacks.html>
966
+ list.run_callbacks :destroy, :before if rails_3
967
+ list.run_callbacks(:before_destroy) if !rails_3
968
+ else
969
+ list.send(:callback, :before_destroy)
970
+ end
971
+
972
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
973
+
974
+ assert_equal 1, ListMixin.find(1).pos
975
+ assert_equal 2, ListMixin.find(2).pos
976
+ assert_equal 2, ListMixin.find(3).pos
977
+ assert_equal 3, ListMixin.find(4).pos
978
+ end
979
+
980
+ def test_before_create_callback_adds_to_bottom
981
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
982
+
983
+ new = ListMixin.create(:parent_id => 5)
984
+ assert_equal 5, new.pos
985
+ assert !new.first?
986
+ assert new.last?
987
+
988
+ assert_equal [1, 2, 3, 4, 5], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
989
+ end
990
+
991
+ def test_before_create_callback_adds_to_given_position
992
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
993
+
994
+ new = ListMixin.create(:pos => 1, :parent_id => 5)
995
+ assert_equal 1, new.pos
996
+ assert new.first?
997
+ assert !new.last?
998
+
999
+ assert_equal [5, 1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
1000
+
1001
+ new = ListMixin.create(:pos => 3, :parent_id => 5)
1002
+ assert_equal 3, new.pos
1003
+ assert !new.first?
1004
+ assert !new.last?
1005
+
1006
+ assert_equal [5, 1, 6, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
1007
+ end
1008
+ end
1009
+
1010
+ class ListSubTestWithDefault < Test::Unit::TestCase
1011
+
1012
+ def setup
1013
+ setup_db_with_default
1014
+ (1..4).each { |i| ((i % 2 == 1) ? ListMixinSub1 : ListMixinSub2).create! :pos => i, :parent_id => 5000 }
1015
+ end
1016
+
1017
+ def teardown
1018
+ teardown_db
1019
+ end
1020
+
1021
+ def test_reordering
1022
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
1023
+
1024
+ ListMixin.find(2).move_lower
1025
+ assert_equal [1, 3, 2, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
1026
+
1027
+ ListMixin.find(2).move_higher
1028
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
1029
+
1030
+ ListMixin.find(1).move_to_bottom
1031
+ assert_equal [2, 3, 4, 1], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
1032
+
1033
+ ListMixin.find(1).move_to_top
1034
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
1035
+
1036
+ ListMixin.find(2).move_to_bottom
1037
+ assert_equal [1, 3, 4, 2], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
1038
+
1039
+ ListMixin.find(4).move_to_top
1040
+ assert_equal [4, 1, 3, 2], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
1041
+ end
1042
+
1043
+ def test_move_to_bottom_with_next_to_last_item
1044
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
1045
+ ListMixin.find(3).move_to_bottom
1046
+ assert_equal [1, 2, 4, 3], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
1047
+ end
1048
+
1049
+ def test_next_prev
1050
+ assert_equal ListMixin.find(2), ListMixin.find(1).lower_item
1051
+ assert_nil ListMixin.find(1).higher_item
1052
+ assert_equal ListMixin.find(3), ListMixin.find(4).higher_item
1053
+ assert_nil ListMixin.find(4).lower_item
1054
+ end
1055
+
1056
+ def test_injection
1057
+ item = ListMixin.new("parent_id"=>1)
1058
+ assert_equal '"mixins"."parent_id" = 1', item.scope_condition
1059
+ assert_equal "pos", item.position_column
1060
+ end
1061
+
1062
+ def test_insert_at
1063
+ new = ListMixin.create("parent_id" => 20)
1064
+ assert_equal 1, new.pos
1065
+
1066
+ new = ListMixinSub1.create("parent_id" => 20)
1067
+ assert_equal 2, new.pos
1068
+
1069
+ new = ListMixinSub2.create("parent_id" => 20)
1070
+ assert_equal 3, new.pos
1071
+
1072
+ new4 = ListMixin.create("parent_id" => 20)
1073
+ assert_equal 4, new4.pos
1074
+
1075
+ new4.insert_at(3)
1076
+ assert_equal 3, new4.pos
1077
+
1078
+ new.reload
1079
+ assert_equal 4, new.pos
1080
+
1081
+ new.insert_at(2)
1082
+ assert_equal 2, new.pos
1083
+
1084
+ new4.reload
1085
+ assert_equal 4, new4.pos
1086
+
1087
+ new5 = ListMixinSub1.create("parent_id" => 20)
1088
+ assert_equal 5, new5.pos
1089
+
1090
+ new5.insert_at(1)
1091
+ assert_equal 1, new5.pos
1092
+
1093
+ new4.reload
1094
+ assert_equal 5, new4.pos
1095
+ end
1096
+
1097
+ def test_delete_middle
1098
+ assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
1099
+
1100
+ ListMixin.find(2).destroy
1101
+
1102
+ assert_equal [1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
1103
+
1104
+ assert_equal 1, ListMixin.find(1).pos
1105
+ assert_equal 2, ListMixin.find(3).pos
1106
+ assert_equal 3, ListMixin.find(4).pos
1107
+
1108
+ ListMixin.find(1).destroy
1109
+
1110
+ assert_equal [3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
1111
+
1112
+ assert_equal 1, ListMixin.find(3).pos
1113
+ assert_equal 2, ListMixin.find(4).pos
1114
+ end
1115
+
1116
+ end
1117
+
1118
+ class ArrayScopeListTestWithDefault < Test::Unit::TestCase
1119
+
1120
+ def setup
1121
+ setup_db_with_default
1122
+ (1..4).each { |counter| ArrayScopeListMixin.create! :pos => counter, :parent_id => 5, :parent_type => 'ParentClass' }
1123
+ end
1124
+
1125
+ def teardown
1126
+ teardown_db
1127
+ end
1128
+
1129
+ def test_reordering
1130
+ assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
1131
+
1132
+ ArrayScopeListMixin.find(2).move_lower
1133
+ assert_equal [1, 3, 2, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
1134
+
1135
+ ArrayScopeListMixin.find(2).move_higher
1136
+ assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
1137
+
1138
+ ArrayScopeListMixin.find(1).move_to_bottom
1139
+ assert_equal [2, 3, 4, 1], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
1140
+
1141
+ ArrayScopeListMixin.find(1).move_to_top
1142
+ assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
1143
+
1144
+ ArrayScopeListMixin.find(2).move_to_bottom
1145
+ assert_equal [1, 3, 4, 2], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
1146
+
1147
+ ArrayScopeListMixin.find(4).move_to_top
1148
+ assert_equal [4, 1, 3, 2], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
1149
+ end
1150
+
1151
+ def test_move_to_bottom_with_next_to_last_item
1152
+ assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
1153
+ ArrayScopeListMixin.find(3).move_to_bottom
1154
+ assert_equal [1, 2, 4, 3], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
1155
+ end
1156
+
1157
+ def test_next_prev
1158
+ assert_equal ArrayScopeListMixin.find(2), ArrayScopeListMixin.find(1).lower_item
1159
+ assert_nil ArrayScopeListMixin.find(1).higher_item
1160
+ assert_equal ArrayScopeListMixin.find(3), ArrayScopeListMixin.find(4).higher_item
1161
+ assert_nil ArrayScopeListMixin.find(4).lower_item
1162
+ end
1163
+
1164
+ def test_injection
1165
+ item = ArrayScopeListMixin.new(:parent_id => 1, :parent_type => 'ParentClass')
1166
+ assert_equal '"mixins"."parent_id" = 1 AND "mixins"."parent_type" = \'ParentClass\'', item.scope_condition
1167
+ assert_equal "pos", item.position_column
1168
+ end
1169
+
1170
+ def test_insert
1171
+ new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
1172
+ assert_equal 1, new.pos
1173
+ assert new.first?
1174
+ assert new.last?
1175
+
1176
+ new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
1177
+ assert_equal 2, new.pos
1178
+ assert !new.first?
1179
+ assert new.last?
1180
+
1181
+ new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
1182
+ assert_equal 3, new.pos
1183
+ assert !new.first?
1184
+ assert new.last?
1185
+
1186
+ new = ArrayScopeListMixin.create(:parent_id => 0, :parent_type => 'ParentClass')
1187
+ assert_equal 1, new.pos
1188
+ assert new.first?
1189
+ assert new.last?
1190
+ end
1191
+
1192
+ def test_insert_at
1193
+ new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
1194
+ assert_equal 1, new.pos
1195
+
1196
+ new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
1197
+ assert_equal 2, new.pos
1198
+
1199
+ new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
1200
+ assert_equal 3, new.pos
1201
+
1202
+ new4 = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
1203
+ assert_equal 4, new4.pos
1204
+
1205
+ new4.insert_at(3)
1206
+ assert_equal 3, new4.pos
1207
+
1208
+ new.reload
1209
+ assert_equal 4, new.pos
1210
+
1211
+ new.insert_at(2)
1212
+ assert_equal 2, new.pos
1213
+
1214
+ new4.reload
1215
+ assert_equal 4, new4.pos
1216
+
1217
+ new5 = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
1218
+ assert_equal 5, new5.pos
1219
+
1220
+ new5.insert_at(1)
1221
+ assert_equal 1, new5.pos
1222
+
1223
+ new4.reload
1224
+ assert_equal 5, new4.pos
1225
+ end
1226
+
1227
+ def test_delete_middle
1228
+ assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
1229
+
1230
+ ArrayScopeListMixin.find(2).destroy
1231
+
1232
+ assert_equal [1, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
1233
+
1234
+ assert_equal 1, ArrayScopeListMixin.find(1).pos
1235
+ assert_equal 2, ArrayScopeListMixin.find(3).pos
1236
+ assert_equal 3, ArrayScopeListMixin.find(4).pos
1237
+
1238
+ ArrayScopeListMixin.find(1).destroy
1239
+
1240
+ assert_equal [3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
1241
+
1242
+ assert_equal 1, ArrayScopeListMixin.find(3).pos
1243
+ assert_equal 2, ArrayScopeListMixin.find(4).pos
1244
+ end
1245
+
1246
+ def test_remove_from_list_should_then_fail_in_list?
1247
+ assert_equal true, ArrayScopeListMixin.find(1).in_list?
1248
+ ArrayScopeListMixin.find(1).remove_from_list
1249
+ assert_equal false, ArrayScopeListMixin.find(1).in_list?
1250
+ end
1251
+
1252
+ def test_remove_from_list_should_set_position_to_nil
1253
+ assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
1254
+
1255
+ ArrayScopeListMixin.find(2).remove_from_list
1256
+
1257
+ assert_equal [2, 1, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
1258
+
1259
+ assert_equal 1, ArrayScopeListMixin.find(1).pos
1260
+ assert_equal nil, ArrayScopeListMixin.find(2).pos
1261
+ assert_equal 2, ArrayScopeListMixin.find(3).pos
1262
+ assert_equal 3, ArrayScopeListMixin.find(4).pos
1263
+ end
1264
+
1265
+ def test_remove_before_destroy_does_not_shift_lower_items_twice
1266
+ assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
1267
+
1268
+ ArrayScopeListMixin.find(2).remove_from_list
1269
+ ArrayScopeListMixin.find(2).destroy
1270
+
1271
+ assert_equal [1, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
1272
+
1273
+ assert_equal 1, ArrayScopeListMixin.find(1).pos
1274
+ assert_equal 2, ArrayScopeListMixin.find(3).pos
1275
+ assert_equal 3, ArrayScopeListMixin.find(4).pos
1276
+ end
1277
+
1278
+ end
1279
+
1280
+ class DefaultScopedTest < Test::Unit::TestCase
1281
+ def setup
1282
+ setup_db
1283
+ (1..4).each { |counter| DefaultScopedMixin.create! :pos => counter }
1284
+ end
1285
+
1286
+ def teardown
1287
+ teardown_db
1288
+ end
1289
+
1290
+ def test_insert
1291
+ new = DefaultScopedMixin.create
1292
+ assert_equal 5, new.pos
1293
+ assert !new.first?
1294
+ assert new.last?
1295
+
1296
+ new = DefaultScopedMixin.create
1297
+ assert_equal 6, new.pos
1298
+ assert !new.first?
1299
+ assert new.last?
1300
+
1301
+ new = DefaultScopedMixin.create
1302
+ assert_equal 7, new.pos
1303
+ assert !new.first?
1304
+ assert new.last?
1305
+ end
1306
+
1307
+ def test_reordering
1308
+ assert_equal [1, 2, 3, 4], DefaultScopedMixin.find(:all).map(&:id)
1309
+
1310
+ DefaultScopedMixin.find(2).move_lower
1311
+ assert_equal [1, 3, 2, 4], DefaultScopedMixin.find(:all).map(&:id)
1312
+
1313
+ DefaultScopedMixin.find(2).move_higher
1314
+ assert_equal [1, 2, 3, 4], DefaultScopedMixin.find(:all).map(&:id)
1315
+
1316
+ DefaultScopedMixin.find(1).move_to_bottom
1317
+ assert_equal [2, 3, 4, 1], DefaultScopedMixin.find(:all).map(&:id)
1318
+
1319
+ DefaultScopedMixin.find(1).move_to_top
1320
+ assert_equal [1, 2, 3, 4], DefaultScopedMixin.find(:all).map(&:id)
1321
+
1322
+ DefaultScopedMixin.find(2).move_to_bottom
1323
+ assert_equal [1, 3, 4, 2], DefaultScopedMixin.find(:all).map(&:id)
1324
+
1325
+ DefaultScopedMixin.find(4).move_to_top
1326
+ assert_equal [4, 1, 3, 2], DefaultScopedMixin.find(:all).map(&:id)
1327
+ end
1328
+
1329
+ def test_insert_at
1330
+ new = DefaultScopedMixin.create
1331
+ assert_equal 5, new.pos
1332
+
1333
+ new = DefaultScopedMixin.create
1334
+ assert_equal 6, new.pos
1335
+
1336
+ new = DefaultScopedMixin.create
1337
+ assert_equal 7, new.pos
1338
+
1339
+ new4 = DefaultScopedMixin.create
1340
+ assert_equal 8, new4.pos
1341
+
1342
+ new4.insert_at(2)
1343
+ assert_equal 2, new4.pos
1344
+
1345
+ new.reload
1346
+ assert_equal 8, new.pos
1347
+
1348
+ new.insert_at(2)
1349
+ assert_equal 2, new.pos
1350
+
1351
+ new4.reload
1352
+ assert_equal 3, new4.pos
1353
+
1354
+ new5 = DefaultScopedMixin.create
1355
+ assert_equal 9, new5.pos
1356
+
1357
+ new5.insert_at(1)
1358
+ assert_equal 1, new5.pos
1359
+
1360
+ new4.reload
1361
+ assert_equal 4, new4.pos
1362
+ end
1363
+ end
1364
+
1365
+ class CallbackTest < Test::Unit::TestCase
1366
+ def setup
1367
+ $after_save_called = nil
1368
+ $before_save_called = nil
1369
+ setup_db
1370
+ (1..4).each { |counter| DefaultScopedMixin.create! :pos => counter }
1371
+ end
1372
+
1373
+ def teardown
1374
+ teardown_db
1375
+ end
1376
+
1377
+ def test_position_is_updated_within_object
1378
+ @item = CallbackMixin.first
1379
+ @item.move_to_bottom
1380
+
1381
+ assert_equal 4, @item.pos
1382
+ end
1383
+
1384
+ def test_object_is_not_marked_dirty
1385
+ @item = CallbackMixin.first
1386
+ @item.move_to_bottom
1387
+
1388
+ assert !@item.changed?
1389
+ assert_nil @item.pos_change
1390
+ end
1391
+
1392
+ def test_position_update_does_not_trigger_before_save_callback
1393
+ @item = CallbackMixin.first
1394
+ @item.move_to_bottom
1395
+
1396
+ assert_nil $before_save_called
1397
+ end
1398
+
1399
+ def test_position_update_does_not_trigger_after_save_callback
1400
+ @item = CallbackMixin.first
1401
+ @item.move_to_bottom
1402
+
1403
+ assert_nil $after_save_called
1404
+ end
1405
+ end