acts_as_list 0.9.17 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -89,20 +89,30 @@ module ActiveRecord
89
89
 
90
90
  class << self
91
91
  def apply_to(klasses)
92
- extracted_klasses.push(*klasses)
92
+ klasses.map {|klass| add_klass(klass)}
93
93
  yield
94
94
  ensure
95
- extracted_klasses.clear
95
+ klasses.map {|klass| remove_klass(klass)}
96
96
  end
97
97
 
98
98
  def applied_to?(klass)
99
- !(klass.ancestors & extracted_klasses).empty?
99
+ !(klass.ancestors & extracted_klasses.keys).empty?
100
100
  end
101
101
 
102
102
  private
103
103
 
104
104
  def extracted_klasses
105
- Thread.current[:act_as_list_no_update] ||= []
105
+ Thread.current[:act_as_list_no_update] ||= {}
106
+ end
107
+
108
+ def add_klass(klass)
109
+ extracted_klasses[klass] = 0 unless extracted_klasses.key?(klass)
110
+ extracted_klasses[klass] += 1
111
+ end
112
+
113
+ def remove_klass(klass)
114
+ extracted_klasses[klass] -= 1
115
+ extracted_klasses.delete(klass) if extracted_klasses[klass] <= 0
106
116
  end
107
117
  end
108
118
 
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecord::Acts::List::PositionColumnMethodDefiner #:nodoc:
4
- def self.call(caller_class, position_column)
5
- define_class_methods(caller_class, position_column)
4
+ def self.call(caller_class, position_column, touch_on_update)
5
+ define_class_methods(caller_class, position_column, touch_on_update)
6
6
  define_instance_methods(caller_class, position_column)
7
7
 
8
8
  if mass_assignment_protection_was_used_by_user?(caller_class)
@@ -12,7 +12,7 @@ module ActiveRecord::Acts::List::PositionColumnMethodDefiner #:nodoc:
12
12
 
13
13
  private
14
14
 
15
- def self.define_class_methods(caller_class, position_column)
15
+ def self.define_class_methods(caller_class, position_column, touch_on_update)
16
16
  caller_class.class_eval do
17
17
  define_singleton_method :quoted_position_column do
18
18
  @_quoted_position_column ||= connection.quote_column_name(position_column)
@@ -22,6 +22,18 @@ module ActiveRecord::Acts::List::PositionColumnMethodDefiner #:nodoc:
22
22
  @_quoted_position_column_with_table_name ||= "#{caller_class.quoted_table_name}.#{quoted_position_column}"
23
23
  end
24
24
 
25
+ define_singleton_method :decrement_sequentially do
26
+ pluck(primary_key).each do |id|
27
+ where(primary_key => id).decrement_all
28
+ end
29
+ end
30
+
31
+ define_singleton_method :increment_sequentially do
32
+ pluck(primary_key).each do |id|
33
+ where(primary_key => id).increment_all
34
+ end
35
+ end
36
+
25
37
  define_singleton_method :decrement_all do
26
38
  update_all_with_touch "#{quoted_position_column} = (#{quoted_position_column_with_table_name} - 1)"
27
39
  end
@@ -31,7 +43,8 @@ module ActiveRecord::Acts::List::PositionColumnMethodDefiner #:nodoc:
31
43
  end
32
44
 
33
45
  define_singleton_method :update_all_with_touch do |updates|
34
- update_all(updates + touch_record_sql)
46
+ updates += touch_record_sql if touch_on_update
47
+ update_all(updates)
35
48
  end
36
49
 
37
50
  private
@@ -51,7 +64,7 @@ module ActiveRecord::Acts::List::PositionColumnMethodDefiner #:nodoc:
51
64
  end
52
65
 
53
66
  define_method :"#{position_column}=" do |position|
54
- write_attribute(position_column, position)
67
+ self[position_column] = position
55
68
  @position_changed = true
56
69
  end
57
70
 
@@ -4,7 +4,7 @@ module ActiveRecord::Acts::List::ScopeMethodDefiner #:nodoc:
4
4
  extend ActiveSupport::Inflector
5
5
 
6
6
  def self.call(caller_class, scope)
7
- scope = idify(scope) if scope.is_a?(Symbol)
7
+ scope = idify(caller_class, scope) if scope.is_a?(Symbol)
8
8
 
9
9
  caller_class.class_eval do
10
10
  define_method :scope_name do
@@ -21,7 +21,6 @@ module ActiveRecord::Acts::List::ScopeMethodDefiner #:nodoc:
21
21
  end
22
22
 
23
23
  define_method :destroyed_via_scope? do
24
- return false if ActiveRecord::VERSION::MAJOR < 4
25
24
  scope == (destroyed_by_association && destroyed_by_association.foreign_key.to_sym)
26
25
  end
27
26
  elsif scope.is_a?(Array)
@@ -45,7 +44,6 @@ module ActiveRecord::Acts::List::ScopeMethodDefiner #:nodoc:
45
44
  end
46
45
 
47
46
  define_method :destroyed_via_scope? do
48
- return false if ActiveRecord::VERSION::MAJOR < 4
49
47
  scope_condition.keys.include? (destroyed_by_association && destroyed_by_association.foreign_key.to_sym)
50
48
  end
51
49
  else
@@ -66,9 +64,13 @@ module ActiveRecord::Acts::List::ScopeMethodDefiner #:nodoc:
66
64
  end
67
65
  end
68
66
 
69
- def self.idify(name)
67
+ def self.idify(caller_class, name)
70
68
  return name if name.to_s =~ /_id$/
71
69
 
72
- foreign_key(name).to_sym
70
+ if caller_class.reflections.key?(name.to_s)
71
+ caller_class.reflections[name.to_s].foreign_key.to_sym
72
+ else
73
+ foreign_key(name).to_sym
74
+ end
73
75
  end
74
76
  end
@@ -7,7 +7,7 @@ module ActiveRecord::Acts::List::SequentialUpdatesMethodDefiner #:nodoc:
7
7
  if !defined?(@sequential_updates)
8
8
  if sequential_updates_option.nil?
9
9
  table_exists =
10
- if ActiveRecord::VERSION::MAJOR >= 5
10
+ if active_record_version_is?('>= 5')
11
11
  caller_class.connection.data_source_exists?(caller_class.table_name)
12
12
  else
13
13
  caller_class.connection.table_exists?(caller_class.table_name)
@@ -3,7 +3,7 @@
3
3
  module ActiveRecord
4
4
  module Acts
5
5
  module List
6
- VERSION = '0.9.17'
6
+ VERSION = '1.0.2'
7
7
  end
8
8
  end
9
9
  end
@@ -13,7 +13,7 @@ rescue Bundler::BundlerError => e
13
13
  end
14
14
  require "active_record"
15
15
  require "minitest/autorun"
16
- require "mocha/mini_test"
16
+ require "mocha/minitest"
17
17
  require "#{File.dirname(__FILE__)}/../init"
18
18
 
19
19
  if defined?(ActiveRecord::VERSION) &&
@@ -27,15 +27,6 @@ db_config = YAML.load_file(File.expand_path("../database.yml", __FILE__)).fetch(
27
27
  ActiveRecord::Base.establish_connection(db_config)
28
28
  ActiveRecord::Schema.verbose = false
29
29
 
30
- # Returns true if ActiveRecord is rails 3, 4 version
31
- def rails_3
32
- defined?(ActiveRecord::VERSION) && ActiveRecord::VERSION::MAJOR >= 3
33
- end
34
-
35
- def rails_4
36
- defined?(ActiveRecord::VERSION) && ActiveRecord::VERSION::MAJOR >= 4
37
- end
38
-
39
30
  def teardown_db
40
31
  if ActiveRecord::VERSION::MAJOR >= 5
41
32
  tables = ActiveRecord::Base.connection.data_sources
@@ -10,6 +10,13 @@ module Shared
10
10
  end
11
11
  end
12
12
 
13
+ def test_current_position
14
+ first_item = ListMixin.where(parent_id: 5).first
15
+ assert_equal 1, first_item.current_position
16
+ first_item.remove_from_list
17
+ assert_nil first_item.current_position
18
+ end
19
+
13
20
  def test_reordering
14
21
  assert_equal [1, 2, 3, 4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
15
22
 
@@ -230,12 +237,9 @@ module Shared
230
237
  # We need to trigger all the before_destroy callbacks without actually
231
238
  # destroying the record so we can see the affect the callbacks have on
232
239
  # the record.
233
- # NOTE: Hotfix for rails3 ActiveRecord
234
240
  list = ListMixin.where(id: 2).first
235
241
  if list.respond_to?(:run_callbacks)
236
- # Refactored to work according to Rails3 ActiveRSupport Callbacks <http://api.rubyonrails.org/classes/ActiveSupport/Callbacks.html>
237
- list.run_callbacks(:destroy) if rails_3
238
- list.run_callbacks(:before_destroy) if !rails_3
242
+ list.run_callbacks(:destroy)
239
243
  else
240
244
  list.send(:callback, :before_destroy)
241
245
  end
@@ -47,7 +47,7 @@ module Shared
47
47
 
48
48
  def test_next_prev_not_regular_sequence
49
49
  ListMixin.all.each do |item|
50
- item.update_attributes(pos: item.pos * 5)
50
+ item.update pos: item.pos * 5
51
51
  end
52
52
 
53
53
  assert_equal [1, 2, 3, 4], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
@@ -39,11 +39,18 @@ def setup_db(position_options = {})
39
39
  t.column :order, :integer
40
40
  end
41
41
 
42
- mixins = [ Mixin, ListMixin, ListMixinSub1, ListMixinSub2, ListWithStringScopeMixin,
43
- ArrayScopeListMixin, ZeroBasedMixin, DefaultScopedMixin,
44
- DefaultScopedWhereMixin, TopAdditionMixin, NoAdditionMixin, QuotedList ]
42
+ # This table is used to test table names with different primary_key columns
43
+ ActiveRecord::Base.connection.create_table 'altid-table', primary_key: 'altid' do |t|
44
+ t.column :pos, :integer
45
+ t.column :created_at, :datetime
46
+ t.column :updated_at, :datetime
47
+ end
45
48
 
46
- mixins << EnumArrayScopeListMixin if rails_4
49
+ ActiveRecord::Base.connection.add_index 'altid-table', :pos, unique: true
50
+
51
+ mixins = [ Mixin, ListMixin, ListMixinSub1, ListMixinSub2, ListWithStringScopeMixin,
52
+ ArrayScopeListMixin, ZeroBasedMixin, DefaultScopedMixin, EnumArrayScopeListMixin,
53
+ DefaultScopedWhereMixin, TopAdditionMixin, NoAdditionMixin, QuotedList, TouchDisabledMixin ]
47
54
 
48
55
  ActiveRecord::Base.connection.schema_cache.clear!
49
56
  mixins.each do |klass|
@@ -63,23 +70,19 @@ class ListMixin < Mixin
63
70
  acts_as_list column: "pos", scope: :parent
64
71
  end
65
72
 
73
+ class TouchDisabledMixin < Mixin
74
+ acts_as_list column: "pos", touch_on_update: false
75
+ end
76
+
66
77
  class ListMixinSub1 < ListMixin
67
78
  end
68
79
 
69
80
  class ListMixinSub2 < ListMixin
70
- if rails_3
71
- validates :pos, presence: true
72
- else
73
- validates_presence_of :pos
74
- end
81
+ validates :pos, presence: true
75
82
  end
76
83
 
77
84
  class ListMixinError < ListMixin
78
- if rails_3
79
- validates :state, presence: true
80
- else
81
- validates_presence_of :state
82
- end
85
+ validates :state, presence: true
83
86
  end
84
87
 
85
88
  class ListWithStringScopeMixin < Mixin
@@ -94,13 +97,11 @@ class ArrayScopeListWithHashMixin < Mixin
94
97
  acts_as_list column: "pos", scope: [:parent_id, state: nil]
95
98
  end
96
99
 
97
- if rails_4
98
- class EnumArrayScopeListMixin < Mixin
99
- STATE_VALUES = %w(active archived)
100
- enum state: STATE_VALUES
100
+ class EnumArrayScopeListMixin < Mixin
101
+ STATE_VALUES = %w(active archived)
102
+ enum state: STATE_VALUES
101
103
 
102
- acts_as_list column: "pos", scope: [:parent_id, :state]
103
- end
104
+ acts_as_list column: "pos", scope: [:parent_id, :state]
104
105
  end
105
106
 
106
107
  class ZeroBasedMixin < Mixin
@@ -117,13 +118,7 @@ class DefaultScopedWhereMixin < Mixin
117
118
  default_scope { order('pos ASC').where(active: true) }
118
119
 
119
120
  def self.for_active_false_tests
120
- if ActiveRecord::VERSION::MAJOR < 4
121
- unscoped do
122
- order('pos ASC').where(active: false)
123
- end
124
- else
125
- unscope(:where).where(active: false)
126
- end
121
+ unscope(:where).where(active: false)
127
122
  end
128
123
  end
129
124
 
@@ -131,6 +126,17 @@ class SequentialUpdatesDefault < Mixin
131
126
  acts_as_list column: "pos"
132
127
  end
133
128
 
129
+ class SequentialUpdatesAltId < ActiveRecord::Base
130
+ self.table_name = "altid-table"
131
+ self.primary_key = "altid"
132
+
133
+ acts_as_list column: "pos"
134
+ end
135
+
136
+ class SequentialUpdatesAltIdTouchDisabled < SequentialUpdatesAltId
137
+ acts_as_list column: "pos", touch_on_update: false
138
+ end
139
+
134
140
  class SequentialUpdatesFalseMixin < Mixin
135
141
  acts_as_list column: "pos", sequential_updates: false
136
142
  end
@@ -146,7 +152,7 @@ end
146
152
  ##
147
153
  # The way we track changes to
148
154
  # scope and position can get tripped up
149
- # by someone using update_attributes within
155
+ # by someone using update within
150
156
  # a callback because it causes multiple passes
151
157
  # through the callback chain
152
158
  module CallbackMixin
@@ -161,7 +167,7 @@ module CallbackMixin
161
167
  # doesn't matter what column changes, just
162
168
  # need to change something
163
169
 
164
- self.update_attributes(active: !self.active)
170
+ self.update active: !self.active
165
171
  end
166
172
  end
167
173
  end
@@ -625,7 +631,7 @@ class MultipleListsTest < ActsAsListTestCase
625
631
  def test_check_scope_order
626
632
  assert_equal [1, 2, 3, 4], ListMixin.where(:parent_id => 1).order('pos').map(&:id)
627
633
  assert_equal [5, 6, 7, 8], ListMixin.where(:parent_id => 2).order('pos').map(&:id)
628
- ListMixin.find(4).update_attributes(:parent_id => 2, :pos => 2)
634
+ ListMixin.find(4).update :parent_id => 2, :pos => 2
629
635
  assert_equal [1, 2, 3], ListMixin.where(:parent_id => 1).order('pos').map(&:id)
630
636
  assert_equal [5, 4, 6, 7, 8], ListMixin.where(:parent_id => 2).order('pos').map(&:id)
631
637
  end
@@ -633,34 +639,32 @@ class MultipleListsTest < ActsAsListTestCase
633
639
  def test_check_scope_position
634
640
  assert_equal [1, 2, 3, 4], ListMixin.where(:parent_id => 1).map(&:pos)
635
641
  assert_equal [1, 2, 3, 4], ListMixin.where(:parent_id => 2).map(&:pos)
636
- ListMixin.find(4).update_attributes(:parent_id => 2, :pos => 2)
642
+ ListMixin.find(4).update :parent_id => 2, :pos => 2
637
643
  assert_equal [1, 2, 3], ListMixin.where(:parent_id => 1).order('pos').map(&:pos)
638
644
  assert_equal [1, 2, 3, 4, 5], ListMixin.where(:parent_id => 2).order('pos').map(&:pos)
639
645
  end
640
646
  end
641
647
 
642
- if rails_4
643
- class EnumArrayScopeListMixinTest < ActsAsListTestCase
644
- def setup
645
- setup_db
646
- EnumArrayScopeListMixin.create! :parent_id => 1, :state => EnumArrayScopeListMixin.states['active']
647
- EnumArrayScopeListMixin.create! :parent_id => 1, :state => EnumArrayScopeListMixin.states['archived']
648
- EnumArrayScopeListMixin.create! :parent_id => 2, :state => EnumArrayScopeListMixin.states["active"]
649
- EnumArrayScopeListMixin.create! :parent_id => 2, :state => EnumArrayScopeListMixin.states["archived"]
650
- end
648
+ class EnumArrayScopeListMixinTest < ActsAsListTestCase
649
+ def setup
650
+ setup_db
651
+ EnumArrayScopeListMixin.create! :parent_id => 1, :state => EnumArrayScopeListMixin.states['active']
652
+ EnumArrayScopeListMixin.create! :parent_id => 1, :state => EnumArrayScopeListMixin.states['archived']
653
+ EnumArrayScopeListMixin.create! :parent_id => 2, :state => EnumArrayScopeListMixin.states["active"]
654
+ EnumArrayScopeListMixin.create! :parent_id => 2, :state => EnumArrayScopeListMixin.states["archived"]
655
+ end
651
656
 
652
- def test_positions
653
- assert_equal [1], EnumArrayScopeListMixin.where(:parent_id => 1, :state => EnumArrayScopeListMixin.states['active']).map(&:pos)
654
- assert_equal [1], EnumArrayScopeListMixin.where(:parent_id => 1, :state => EnumArrayScopeListMixin.states['archived']).map(&:pos)
655
- assert_equal [1], EnumArrayScopeListMixin.where(:parent_id => 2, :state => EnumArrayScopeListMixin.states['active']).map(&:pos)
656
- assert_equal [1], EnumArrayScopeListMixin.where(:parent_id => 2, :state => EnumArrayScopeListMixin.states['archived']).map(&:pos)
657
- end
657
+ def test_positions
658
+ assert_equal [1], EnumArrayScopeListMixin.where(:parent_id => 1, :state => EnumArrayScopeListMixin.states['active']).map(&:pos)
659
+ assert_equal [1], EnumArrayScopeListMixin.where(:parent_id => 1, :state => EnumArrayScopeListMixin.states['archived']).map(&:pos)
660
+ assert_equal [1], EnumArrayScopeListMixin.where(:parent_id => 2, :state => EnumArrayScopeListMixin.states['active']).map(&:pos)
661
+ assert_equal [1], EnumArrayScopeListMixin.where(:parent_id => 2, :state => EnumArrayScopeListMixin.states['archived']).map(&:pos)
662
+ end
658
663
 
659
- def test_update_state
660
- active_item = EnumArrayScopeListMixin.find_by(:parent_id => 2, :state => EnumArrayScopeListMixin.states['active'])
661
- active_item.update(state: EnumArrayScopeListMixin.states['archived'])
662
- assert_equal [1, 2], EnumArrayScopeListMixin.where(:parent_id => 2, :state => EnumArrayScopeListMixin.states['archived']).map(&:pos).sort
663
- end
664
+ def test_update_state
665
+ active_item = EnumArrayScopeListMixin.find_by(:parent_id => 2, :state => EnumArrayScopeListMixin.states['active'])
666
+ active_item.update(state: EnumArrayScopeListMixin.states['archived'])
667
+ assert_equal [1, 2], EnumArrayScopeListMixin.where(:parent_id => 2, :state => EnumArrayScopeListMixin.states['archived']).map(&:pos).sort
664
668
  end
665
669
  end
666
670
 
@@ -675,7 +679,7 @@ class MultipleListsArrayScopeTest < ActsAsListTestCase
675
679
  def test_order_after_all_scope_properties_are_changed
676
680
  assert_equal [1, 2, 3, 4], ArrayScopeListMixin.where(:parent_id => 1, :parent_type => 'anything').order('pos').map(&:id)
677
681
  assert_equal [5, 6, 7, 8], ArrayScopeListMixin.where(:parent_id => 2, :parent_type => 'something').order('pos').map(&:id)
678
- ArrayScopeListMixin.find(2).update_attributes(:parent_id => 2, :pos => 2,:parent_type => 'something')
682
+ ArrayScopeListMixin.find(2).update :parent_id => 2, :pos => 2,:parent_type => 'something'
679
683
  assert_equal [1, 3, 4], ArrayScopeListMixin.where(:parent_id => 1,:parent_type => 'anything').order('pos').map(&:id)
680
684
  assert_equal [5, 2, 6, 7, 8], ArrayScopeListMixin.where(:parent_id => 2,:parent_type => 'something').order('pos').map(&:id)
681
685
  end
@@ -683,7 +687,7 @@ class MultipleListsArrayScopeTest < ActsAsListTestCase
683
687
  def test_position_after_all_scope_properties_are_changed
684
688
  assert_equal [1, 2, 3, 4], ArrayScopeListMixin.where(:parent_id => 1, :parent_type => 'anything').map(&:pos)
685
689
  assert_equal [1, 2, 3, 4], ArrayScopeListMixin.where(:parent_id => 2, :parent_type => 'something').map(&:pos)
686
- ArrayScopeListMixin.find(4).update_attributes(:parent_id => 2, :pos => 2, :parent_type => 'something')
690
+ ArrayScopeListMixin.find(4).update :parent_id => 2, :pos => 2, :parent_type => 'something'
687
691
  assert_equal [1, 2, 3], ArrayScopeListMixin.where(:parent_id => 1, :parent_type => 'anything').order('pos').map(&:pos)
688
692
  assert_equal [1, 2, 3, 4, 5], ArrayScopeListMixin.where(:parent_id => 2, :parent_type => 'something').order('pos').map(&:pos)
689
693
  end
@@ -691,7 +695,7 @@ class MultipleListsArrayScopeTest < ActsAsListTestCase
691
695
  def test_order_after_one_scope_property_is_changed
692
696
  assert_equal [1, 2, 3, 4], ArrayScopeListMixin.where(:parent_id => 1, :parent_type => 'anything').order('pos').map(&:id)
693
697
  assert_equal [9, 10, 11, 12], ArrayScopeListMixin.where(:parent_id => 3, :parent_type => 'anything').order('pos').map(&:id)
694
- ArrayScopeListMixin.find(2).update_attributes(:parent_id => 3, :pos => 2)
698
+ ArrayScopeListMixin.find(2).update :parent_id => 3, :pos => 2
695
699
  assert_equal [1, 3, 4], ArrayScopeListMixin.where(:parent_id => 1,:parent_type => 'anything').order('pos').map(&:id)
696
700
  assert_equal [9, 2, 10, 11, 12], ArrayScopeListMixin.where(:parent_id => 3,:parent_type => 'anything').order('pos').map(&:id)
697
701
  end
@@ -699,7 +703,7 @@ class MultipleListsArrayScopeTest < ActsAsListTestCase
699
703
  def test_position_after_one_scope_property_is_changed
700
704
  assert_equal [1, 2, 3, 4], ArrayScopeListMixin.where(:parent_id => 1, :parent_type => 'anything').map(&:pos)
701
705
  assert_equal [1, 2, 3, 4], ArrayScopeListMixin.where(:parent_id => 3, :parent_type => 'anything').map(&:pos)
702
- ArrayScopeListMixin.find(4).update_attributes(:parent_id => 3, :pos => 2)
706
+ ArrayScopeListMixin.find(4).update :parent_id => 3, :pos => 2
703
707
  assert_equal [1, 2, 3], ArrayScopeListMixin.where(:parent_id => 1, :parent_type => 'anything').order('pos').map(&:pos)
704
708
  assert_equal [1, 2, 3, 4, 5], ArrayScopeListMixin.where(:parent_id => 3, :parent_type => 'anything').order('pos').map(&:pos)
705
709
  end
@@ -707,7 +711,7 @@ class MultipleListsArrayScopeTest < ActsAsListTestCase
707
711
  def test_order_after_moving_to_empty_list
708
712
  assert_equal [1, 2, 3, 4], ArrayScopeListMixin.where(:parent_id => 1, :parent_type => 'anything').order('pos').map(&:id)
709
713
  assert_equal [], ArrayScopeListMixin.where(:parent_id => 4, :parent_type => 'anything').order('pos').map(&:id)
710
- ArrayScopeListMixin.find(2).update_attributes(:parent_id => 4, :pos => 1)
714
+ ArrayScopeListMixin.find(2).update :parent_id => 4, :pos => 1
711
715
  assert_equal [1, 3, 4], ArrayScopeListMixin.where(:parent_id => 1,:parent_type => 'anything').order('pos').map(&:id)
712
716
  assert_equal [2], ArrayScopeListMixin.where(:parent_id => 4,:parent_type => 'anything').order('pos').map(&:id)
713
717
  end
@@ -715,7 +719,7 @@ class MultipleListsArrayScopeTest < ActsAsListTestCase
715
719
  def test_position_after_moving_to_empty_list
716
720
  assert_equal [1, 2, 3, 4], ArrayScopeListMixin.where(:parent_id => 1, :parent_type => 'anything').map(&:pos)
717
721
  assert_equal [], ArrayScopeListMixin.where(:parent_id => 4, :parent_type => 'anything').map(&:pos)
718
- ArrayScopeListMixin.find(2).update_attributes(:parent_id => 4, :pos => 1)
722
+ ArrayScopeListMixin.find(2).update :parent_id => 4, :pos => 1
719
723
  assert_equal [1, 2, 3], ArrayScopeListMixin.where(:parent_id => 1, :parent_type => 'anything').order('pos').map(&:pos)
720
724
  assert_equal [1], ArrayScopeListMixin.where(:parent_id => 4, :parent_type => 'anything').order('pos').map(&:pos)
721
725
  end
@@ -812,6 +816,41 @@ class TouchTest < ActsAsListTestCase
812
816
  end
813
817
  end
814
818
 
819
+ class TouchDisabledTest < ActsAsListTestCase
820
+ def setup
821
+ setup_db
822
+ Timecop.freeze(yesterday) do
823
+ 4.times { TouchDisabledMixin.create! }
824
+ end
825
+ end
826
+
827
+ def now
828
+ @now ||= Time.current.change(usec: 0)
829
+ end
830
+
831
+ def yesterday
832
+ @yesterday ||= 1.day.ago
833
+ end
834
+
835
+ def updated_ats
836
+ TouchDisabledMixin.order(:id).pluck(:updated_at)
837
+ end
838
+
839
+ def positions
840
+ ListMixin.order(:id).pluck(:pos)
841
+ end
842
+
843
+ def test_deleting_item_does_not_touch_higher_items
844
+ Timecop.freeze(now) do
845
+ TouchDisabledMixin.first.destroy
846
+ updated_ats.each do |updated_at|
847
+ assert_equal updated_at.to_i, yesterday.to_i
848
+ end
849
+ assert_equal positions, [1, 2, 3]
850
+ end
851
+ end
852
+ end
853
+
815
854
  class ActsAsListTopTest < ActsAsListTestCase
816
855
  def setup
817
856
  setup_db
@@ -930,4 +969,100 @@ class SequentialUpdatesMixinNotNullUniquePositiveConstraintsTest < ActsAsListTes
930
969
  new_item.insert_at(0)
931
970
  end
932
971
  end
972
+
973
+
974
+ class SequentialUpdatesMixinNotNullUniquePositiveConstraintsTest < ActsAsListTestCase
975
+ def setup
976
+ setup_db null: false, unique: true, positive: true
977
+ (1..4).each { |counter| SequentialUpdatesAltId.create!({pos: counter}) }
978
+ end
979
+
980
+ def test_sequential_updates_default_to_true_with_unique_index
981
+ assert_equal true, SequentialUpdatesAltId.new.send(:sequential_updates?)
982
+ end
983
+
984
+ def test_insert_at
985
+ new = SequentialUpdatesAltId.create
986
+ assert_equal 5, new.pos
987
+
988
+ new.insert_at(1)
989
+ assert_equal 1, new.pos
990
+
991
+ new.insert_at(5)
992
+ assert_equal 5, new.pos
993
+
994
+ new.insert_at(3)
995
+ assert_equal 3, new.pos
996
+ end
997
+
998
+ def test_create_at_top
999
+ new = SequentialUpdatesAltId.create!(pos: 1)
1000
+ assert_equal 1, new.pos
1001
+ end
1002
+
1003
+ def test_move_to_bottom
1004
+ item = SequentialUpdatesAltId.order(:pos).first
1005
+ item.move_to_bottom
1006
+ assert_equal 4, item.pos
1007
+ end
1008
+
1009
+ def test_move_to_top
1010
+ new_item = SequentialUpdatesAltId.create!
1011
+ assert_equal 5, new_item.pos
1012
+
1013
+ new_item.move_to_top
1014
+ assert_equal 1, new_item.pos
1015
+ end
1016
+
1017
+ def test_destroy
1018
+ new_item = SequentialUpdatesAltId.create
1019
+ assert_equal 5, new_item.pos
1020
+
1021
+ new_item.insert_at(2)
1022
+ assert_equal 2, new_item.pos
1023
+
1024
+ new_item.destroy
1025
+ assert_equal [1,2,3,4], SequentialUpdatesAltId.all.map(&:pos).sort
1026
+
1027
+ end
1028
+ end
1029
+
1030
+ class SequentialUpdatesAltIdTouchDisabledTest < ActsAsListTestCase
1031
+ def setup
1032
+ setup_db
1033
+ Timecop.freeze(yesterday) do
1034
+ 4.times { SequentialUpdatesAltIdTouchDisabled.create! }
1035
+ end
1036
+ end
1037
+
1038
+ def now
1039
+ @now ||= Time.current.change(usec: 0)
1040
+ end
1041
+
1042
+ def yesterday
1043
+ @yesterday ||= 1.day.ago
1044
+ end
1045
+
1046
+ def updated_ats
1047
+ SequentialUpdatesAltIdTouchDisabled.order(:altid).pluck(:updated_at)
1048
+ end
1049
+
1050
+ def positions
1051
+ SequentialUpdatesAltIdTouchDisabled.order(:altid).pluck(:pos)
1052
+ end
1053
+
1054
+ def test_sequential_updates_default_to_true_with_unique_index
1055
+ assert_equal true, SequentialUpdatesAltIdTouchDisabled.new.send(:sequential_updates?)
1056
+ end
1057
+
1058
+ def test_deleting_item_does_not_touch_higher_items
1059
+ Timecop.freeze(now) do
1060
+ SequentialUpdatesAltIdTouchDisabled.first.destroy
1061
+ updated_ats.each do |updated_at|
1062
+ assert_equal updated_at.to_i, yesterday.to_i
1063
+ end
1064
+ assert_equal positions, [1, 2, 3]
1065
+ end
1066
+ end
1067
+ end
933
1068
  end