acts_as_list 0.8.2 → 0.9.0

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