acts_as_list 0.8.2 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -15,6 +15,11 @@ module Shared
15
15
  assert !new.first?
16
16
  assert new.last?
17
17
 
18
+ new = ZeroBasedMixin.acts_as_list_no_update { ZeroBasedMixin.create(parent_id: 20) }
19
+ assert_equal_or_nil $default_position, new.pos
20
+ assert !new.first?
21
+ assert !new.last?
22
+
18
23
  new = ZeroBasedMixin.create(parent_id: 20)
19
24
  assert_equal 2, new.pos
20
25
  assert !new.first?
@@ -63,6 +68,9 @@ module Shared
63
68
  new = ZeroBasedMixin.create(parent_id: 20)
64
69
  assert_equal 2, new.pos
65
70
 
71
+ new_noup = ZeroBasedMixin.acts_as_list_no_update { ZeroBasedMixin.create(parent_id: 20) }
72
+ assert_equal_or_nil $default_position, new_noup.pos
73
+
66
74
  new4 = ZeroBasedMixin.create(parent_id: 20)
67
75
  assert_equal 3, new4.pos
68
76
 
@@ -86,6 +94,9 @@ module Shared
86
94
 
87
95
  new4.reload
88
96
  assert_equal 4, new4.pos
97
+
98
+ new_noup.reload
99
+ assert_equal_or_nil $default_position, new_noup.pos
89
100
  end
90
101
  end
91
102
  end
@@ -1,6 +1,7 @@
1
1
  require 'helper'
2
2
 
3
- ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
3
+ db_config = YAML.load_file(File.expand_path("../database.yml", __FILE__)).fetch(ENV["DB"] || "sqlite")
4
+ ActiveRecord::Base.establish_connection(db_config)
4
5
  ActiveRecord::Schema.verbose = false
5
6
 
6
7
  class Section < ActiveRecord::Base
@@ -36,7 +37,12 @@ class JoinedTestCase < Minitest::Test
36
37
  end
37
38
 
38
39
  def teardown
39
- ActiveRecord::Base.connection.tables.each do |table|
40
+ if ActiveRecord::VERSION::MAJOR >= 5
41
+ tables = ActiveRecord::Base.connection.data_sources
42
+ else
43
+ tables = ActiveRecord::Base.connection.tables
44
+ end
45
+ tables.each do |table|
40
46
  ActiveRecord::Base.connection.drop_table(table)
41
47
  end
42
48
  super
@@ -1,16 +1,19 @@
1
1
  # NOTE: following now done in helper.rb (better Readability)
2
2
  require 'helper'
3
3
 
4
- ActiveRecord::Base.establish_connection(
5
- adapter: "sqlite3",
6
- database: 'file:memdb1?mode=memory&cache=shared'
7
- )
4
+ db_config = YAML.load_file(File.expand_path("../database.yml", __FILE__)).fetch(ENV["DB"] || "sqlite")
5
+ ActiveRecord::Base.establish_connection(db_config)
8
6
  ActiveRecord::Schema.verbose = false
9
7
 
10
8
  def setup_db(position_options = {})
9
+ $default_position = position_options[:default]
10
+
11
+ # sqlite cannot drop/rename/alter columns and add constraints after table creation
12
+ sqlite = ENV.fetch("DB", "sqlite") == "sqlite"
13
+
11
14
  # AR caches columns options like defaults etc. Clear them!
12
15
  ActiveRecord::Base.connection.create_table :mixins do |t|
13
- t.column :pos, :integer, position_options
16
+ t.column :pos, :integer, position_options unless position_options[:positive] && sqlite
14
17
  t.column :active, :boolean, default: true
15
18
  t.column :parent_id, :integer
16
19
  t.column :parent_type, :string
@@ -19,6 +22,20 @@ def setup_db(position_options = {})
19
22
  t.column :state, :integer
20
23
  end
21
24
 
25
+ if position_options[:unique] && !(sqlite && position_options[:positive])
26
+ ActiveRecord::Base.connection.add_index :mixins, :pos, unique: true
27
+ end
28
+
29
+ if position_options[:positive]
30
+ if sqlite
31
+ # SQLite cannot add constraint after table creation, also cannot add unique inside ADD COLUMN
32
+ ActiveRecord::Base.connection.execute('ALTER TABLE mixins ADD COLUMN pos integer8 NOT NULL CHECK (pos > 0) DEFAULT 1')
33
+ ActiveRecord::Base.connection.execute('CREATE UNIQUE INDEX index_mixins_on_pos ON mixins(pos)')
34
+ else
35
+ ActiveRecord::Base.connection.execute('ALTER TABLE mixins ADD CONSTRAINT pos_check CHECK (pos > 0)')
36
+ end
37
+ end
38
+
22
39
  # This table is used to test table names and column names quoting
23
40
  ActiveRecord::Base.connection.create_table 'table-name' do |t|
24
41
  t.column :order, :integer
@@ -115,6 +132,14 @@ class DefaultScopedWhereMixin < Mixin
115
132
  end
116
133
  end
117
134
 
135
+ class SequentialUpdatesDefault < Mixin
136
+ acts_as_list column: "pos"
137
+ end
138
+
139
+ class SequentialUpdatesFalseMixin < Mixin
140
+ acts_as_list column: "pos", sequential_updates: false
141
+ end
142
+
118
143
  class TopAdditionMixin < Mixin
119
144
  acts_as_list column: "pos", add_new_at: :top, scope: :parent_id
120
145
  end
@@ -163,13 +188,6 @@ end
163
188
  class TheBaseSubclass < TheBaseClass
164
189
  end
165
190
 
166
- class DBConfigTest < Minitest::Test
167
- def test_db_config
168
- # make sure sqlite3 accepts multi threaded access
169
- assert_equal "file:memdb1?mode=memory&cache=shared", ActiveRecord::Base.connection.pool.spec.config[:database]
170
- end
171
- end
172
-
173
191
  class QuotedList < ActiveRecord::Base
174
192
  self.table_name = 'table-name'
175
193
  acts_as_list column: :order
@@ -239,7 +257,7 @@ class ListTest < ActsAsListTestCase
239
257
  wait_for_it = false
240
258
  threads.each(&:join)
241
259
 
242
- assert_equal (1..n).to_a, ListMixin.where(parent_id: 1).order('pos').map(&:pos)
260
+ assert_equal((1..n).to_a, ListMixin.where(parent_id: 1).order('pos').map(&:pos))
243
261
  end
244
262
  end
245
263
 
@@ -326,6 +344,11 @@ class DefaultScopedTest < ActsAsListTestCase
326
344
  assert !new.first?
327
345
  assert new.last?
328
346
 
347
+ new = DefaultScopedMixin.acts_as_list_no_update { DefaultScopedMixin.create }
348
+ assert_equal_or_nil $default_position, new.pos
349
+ assert_equal $default_position.is_a?(Fixnum), new.first?
350
+ assert !new.last?
351
+
329
352
  new = DefaultScopedMixin.create
330
353
  assert_equal 7, new.pos
331
354
  assert !new.first?
@@ -361,6 +384,9 @@ class DefaultScopedTest < ActsAsListTestCase
361
384
  new = DefaultScopedMixin.create
362
385
  assert_equal 6, new.pos
363
386
 
387
+ new_noup = DefaultScopedMixin.acts_as_list_no_update { DefaultScopedMixin.create }
388
+ assert_equal_or_nil $default_position, new_noup.pos
389
+
364
390
  new = DefaultScopedMixin.create
365
391
  assert_equal 7, new.pos
366
392
 
@@ -387,6 +413,9 @@ class DefaultScopedTest < ActsAsListTestCase
387
413
 
388
414
  new4.reload
389
415
  assert_equal 4, new4.pos
416
+
417
+ new_noup.reload
418
+ assert_equal_or_nil $default_position, new_noup.pos
390
419
  end
391
420
 
392
421
  def test_update_position
@@ -419,6 +448,11 @@ class DefaultScopedWhereTest < ActsAsListTestCase
419
448
  assert !new.first?
420
449
  assert new.last?
421
450
 
451
+ new = DefaultScopedWhereMixin.acts_as_list_no_update { DefaultScopedWhereMixin.create }
452
+ assert_equal_or_nil $default_position, new.pos
453
+ assert_equal $default_position.is_a?(Fixnum), new.first?
454
+ assert !new.last?
455
+
422
456
  new = DefaultScopedWhereMixin.create
423
457
  assert_equal 7, new.pos
424
458
  assert !new.first?
@@ -457,6 +491,9 @@ class DefaultScopedWhereTest < ActsAsListTestCase
457
491
  new = DefaultScopedWhereMixin.create
458
492
  assert_equal 7, new.pos
459
493
 
494
+ new_noup = DefaultScopedWhereMixin.acts_as_list_no_update { DefaultScopedWhereMixin.create }
495
+ assert_equal_or_nil $default_position, new_noup.pos
496
+
460
497
  new4 = DefaultScopedWhereMixin.create
461
498
  assert_equal 8, new4.pos
462
499
 
@@ -480,6 +517,9 @@ class DefaultScopedWhereTest < ActsAsListTestCase
480
517
 
481
518
  new4.reload
482
519
  assert_equal 4, new4.pos
520
+
521
+ new_noup.reload
522
+ assert_equal_or_nil $default_position, new_noup.pos
483
523
  end
484
524
 
485
525
  def test_update_position
@@ -534,10 +574,20 @@ class MultiDestroyTest < ActsAsListTestCase
534
574
  new3 = DefaultScopedMixin.create
535
575
  assert_equal 3, new3.pos
536
576
 
577
+ new4 = DefaultScopedMixin.create
578
+ assert_equal 4, new4.pos
579
+
537
580
  new1.destroy
538
581
  new2.destroy
539
582
  new3.reload
583
+ new4.reload
540
584
  assert_equal 1, new3.pos
585
+ assert_equal 2, new4.pos
586
+
587
+ DefaultScopedMixin.acts_as_list_no_update { new3.destroy }
588
+
589
+ new4.reload
590
+ assert_equal 2, new4.pos
541
591
  end
542
592
  end
543
593
 
@@ -670,65 +720,79 @@ class MultipleListsArrayScopeTest < ActsAsListTestCase
670
720
  end
671
721
  end
672
722
 
723
+ require 'timecop'
724
+
673
725
  class TouchTest < ActsAsListTestCase
674
726
  def setup
675
727
  setup_db
676
- 4.times { ListMixin.create! updated_at: yesterday }
728
+ Timecop.freeze(yesterday) do
729
+ 4.times { ListMixin.create! }
730
+ end
677
731
  end
678
732
 
679
733
  def now
680
- Time.now.utc
734
+ @now ||= Time.current
681
735
  end
682
736
 
683
737
  def yesterday
684
- 1.day.ago
738
+ @yesterday ||= 1.day.ago
685
739
  end
686
740
 
687
741
  def updated_ats
688
- ListMixin.pluck(:updated_at)
742
+ ListMixin.order(:id).pluck(:updated_at)
689
743
  end
690
744
 
691
745
  def test_moving_item_lower_touches_self_and_lower_item
692
- ListMixin.first.move_lower
693
- updated_ats[0..1].each do |updated_at|
694
- assert_in_delta updated_at, now, 1.second
695
- end
696
- updated_ats[2..3].each do |updated_at|
697
- assert_in_delta updated_at, yesterday, 1.second
746
+ Timecop.freeze(now) do
747
+ ListMixin.first.move_lower
748
+ updated_ats[0..1].each do |updated_at|
749
+ assert_equal updated_at.to_i, now.to_i
750
+ end
751
+ updated_ats[2..3].each do |updated_at|
752
+ assert_equal updated_at.to_i, yesterday.to_i
753
+ end
698
754
  end
699
755
  end
700
756
 
701
757
  def test_moving_item_higher_touches_self_and_higher_item
702
- ListMixin.all.second.move_higher
703
- updated_ats[0..1].each do |updated_at|
704
- assert_in_delta updated_at, now, 1.second
705
- end
706
- updated_ats[2..3].each do |updated_at|
707
- assert_in_delta updated_at, yesterday, 1.second
758
+ Timecop.freeze(now) do
759
+ ListMixin.all.second.move_higher
760
+ updated_ats[0..1].each do |updated_at|
761
+ assert_equal updated_at.to_i, now.to_i
762
+ end
763
+ updated_ats[2..3].each do |updated_at|
764
+ assert_equal updated_at.to_i, yesterday.to_i
765
+ end
708
766
  end
709
767
  end
710
768
 
711
769
  def test_moving_item_to_bottom_touches_all_other_items
712
- ListMixin.first.move_to_bottom
713
- updated_ats.each do |updated_at|
714
- assert_in_delta updated_at, now, 1.second
770
+ Timecop.freeze(now) do
771
+ ListMixin.first.move_to_bottom
772
+ updated_ats.each do |updated_at|
773
+ assert_equal updated_at.to_i, now.to_i
774
+ end
715
775
  end
716
776
  end
717
777
 
718
778
  def test_moving_item_to_top_touches_all_other_items
719
- ListMixin.last.move_to_top
720
- updated_ats.each do |updated_at|
721
- assert_in_delta updated_at, now, 1.second
779
+ Timecop.freeze(now) do
780
+ ListMixin.last.move_to_top
781
+ updated_ats.each do |updated_at|
782
+ assert_equal updated_at.to_i, now.to_i
783
+ end
722
784
  end
723
785
  end
724
786
 
725
787
  def test_removing_item_touches_all_lower_items
726
- ListMixin.all.third.remove_from_list
727
- updated_ats[0..1].each do |updated_at|
728
- assert_in_delta updated_at, yesterday, 1.second
729
- end
730
- updated_ats[2..2].each do |updated_at|
731
- assert_in_delta updated_at, now, 1.second
788
+ Timecop.freeze(now) do
789
+ ListMixin.all.third.remove_from_list
790
+ updated_ats[0..1].each do |updated_at|
791
+ assert_equal updated_at.to_i, yesterday.to_i
792
+ end
793
+ updated_ats[2..2].each do |updated_at|
794
+ assert_equal updated_at.to_i, now.to_i
795
+ end
732
796
  end
733
797
  end
734
798
  end
@@ -768,8 +832,9 @@ class NilPositionTest < ActsAsListTestCase
768
832
  new3.reload.pos = 1
769
833
  new3.save
770
834
 
771
- assert_equal [nil, 1, 2], DefaultScopedMixin.all.map(&:pos)
772
- assert_equal [2, 3, 1], DefaultScopedMixin.all.map(&:id)
835
+ assert_equal [1, 2], DefaultScopedMixin.where("pos IS NOT NULL").map(&:pos)
836
+ assert_equal [3, 1], DefaultScopedMixin.where("pos IS NOT NULL").map(&:id)
837
+ assert_nil new2.reload.pos
773
838
 
774
839
  new2.reload.pos = 1
775
840
  new2.save
@@ -777,4 +842,43 @@ class NilPositionTest < ActsAsListTestCase
777
842
  assert_equal [1, 2, 3], DefaultScopedMixin.all.map(&:pos)
778
843
  assert_equal [2, 3, 1], DefaultScopedMixin.all.map(&:id)
779
844
  end
780
- end
845
+ end
846
+
847
+ class SequentialUpdatesOptionDefaultTest < ActsAsListTestCase
848
+ def setup
849
+ setup_db
850
+ end
851
+
852
+ def test_sequential_updates_default_to_false_without_unique_index
853
+ assert_equal false, SequentialUpdatesDefault.new.send(:sequential_updates?)
854
+ end
855
+ end
856
+
857
+ class SequentialUpdatesMixinNotNullUniquePositiveConstraintsTest < ActsAsListTestCase
858
+ def setup
859
+ setup_db null: false, unique: true, positive: true
860
+ (1..4).each { |counter| SequentialUpdatesDefault.create!({pos: counter}) }
861
+ end
862
+
863
+ def test_sequential_updates_default_to_true_with_unique_index
864
+ assert_equal true, SequentialUpdatesDefault.new.send(:sequential_updates?)
865
+ end
866
+
867
+ def test_sequential_updates_option_override_with_false
868
+ assert_equal false, SequentialUpdatesFalseMixin.new.send(:sequential_updates?)
869
+ end
870
+
871
+ def test_insert_at
872
+ new = SequentialUpdatesDefault.create
873
+ assert_equal 5, new.pos
874
+
875
+ new.insert_at(1)
876
+ assert_equal 1, new.pos
877
+
878
+ new.insert_at(5)
879
+ assert_equal 5, new.pos
880
+
881
+ new.insert_at(3)
882
+ assert_equal 3, new.pos
883
+ end
884
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_as_list
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-09-23 00:00:00.000000000 Z
13
+ date: 2017-01-23 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -65,8 +65,17 @@ files:
65
65
  - gemfiles/rails_5_0.gemfile
66
66
  - init.rb
67
67
  - lib/acts_as_list.rb
68
+ - lib/acts_as_list/active_record/acts/add_new_at_method_definer.rb
69
+ - lib/acts_as_list/active_record/acts/aux_method_definer.rb
70
+ - lib/acts_as_list/active_record/acts/callback_definer.rb
71
+ - lib/acts_as_list/active_record/acts/column_method_definer.rb
68
72
  - lib/acts_as_list/active_record/acts/list.rb
73
+ - lib/acts_as_list/active_record/acts/no_update.rb
74
+ - lib/acts_as_list/active_record/acts/scope_method_definer.rb
75
+ - lib/acts_as_list/active_record/acts/sequential_updates_method_definer.rb
76
+ - lib/acts_as_list/active_record/acts/top_of_list_method_definer.rb
69
77
  - lib/acts_as_list/version.rb
78
+ - test/database.yml
70
79
  - test/helper.rb
71
80
  - test/shared.rb
72
81
  - test/shared_array_scope_list.rb
@@ -104,6 +113,7 @@ specification_version: 4
104
113
  summary: A gem adding sorting, reordering capabilities to an active_record model,
105
114
  allowing it to act as a list
106
115
  test_files:
116
+ - test/database.yml
107
117
  - test/helper.rb
108
118
  - test/shared.rb
109
119
  - test/shared_array_scope_list.rb