acts_as_list 0.7.4 → 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.
@@ -0,0 +1,50 @@
1
+ module ActiveRecord
2
+ module Acts
3
+ module List
4
+ module NoUpdate
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ # Lets you selectively disable all act_as_list database updates
9
+ # for the duration of a block.
10
+ #
11
+ # ==== Examples
12
+ # ActiveRecord::Acts::List.acts_as_list_no_update do
13
+ # TodoList....
14
+ # end
15
+ #
16
+ # TodoList.acts_as_list_no_update do
17
+ # TodoList....
18
+ # end
19
+ #
20
+ def acts_as_list_no_update(&block)
21
+ NoUpdate.apply_to(self, &block)
22
+ end
23
+ end
24
+
25
+ class << self
26
+ def apply_to(klass)
27
+ klasses.push(klass)
28
+ yield
29
+ ensure
30
+ klasses.pop
31
+ end
32
+
33
+ def applied_to?(klass)
34
+ klasses.any? { |k| k >= klass }
35
+ end
36
+
37
+ private
38
+
39
+ def klasses
40
+ Thread.current[:act_as_list_no_update] ||= []
41
+ end
42
+ end
43
+
44
+ def act_as_list_no_update?
45
+ NoUpdate.applied_to?(self.class)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,49 @@
1
+ module ActiveRecord::Acts::List::ScopeMethodDefiner #:nodoc:
2
+ extend ActiveSupport::Inflector
3
+
4
+ def self.call(caller_class, scope)
5
+ scope = idify(scope) if scope.is_a?(Symbol)
6
+
7
+ caller_class.class_eval do
8
+ define_method :scope_name do
9
+ scope
10
+ end
11
+
12
+ if scope.is_a?(Symbol)
13
+ define_method :scope_condition do
14
+ { scope => send(:"#{scope}") }
15
+ end
16
+
17
+ define_method :scope_changed? do
18
+ changed.include?(scope_name.to_s)
19
+ end
20
+ elsif scope.is_a?(Array)
21
+ define_method :scope_condition do
22
+ scope.inject({}) do |hash, column|
23
+ hash.merge!({ column.to_sym => read_attribute(column.to_sym) })
24
+ end
25
+ end
26
+
27
+ define_method :scope_changed? do
28
+ (scope_condition.keys & changed.map(&:to_sym)).any?
29
+ end
30
+ else
31
+ define_method :scope_condition do
32
+ eval "%{#{scope}}"
33
+ end
34
+
35
+ define_method :scope_changed? do
36
+ false
37
+ end
38
+ end
39
+
40
+ self.scope :in_list, lambda { where("#{quoted_position_column_with_table_name} IS NOT NULL") }
41
+ end
42
+ end
43
+
44
+ def self.idify(name)
45
+ return name if name.to_s =~ /_id$/
46
+
47
+ foreign_key(name).to_sym
48
+ end
49
+ end
@@ -0,0 +1,21 @@
1
+ module ActiveRecord::Acts::List::SequentialUpdatesMethodDefiner #:nodoc:
2
+ def self.call(caller_class, column, sequential_updates_option)
3
+ caller_class.class_eval do
4
+ define_method :sequential_updates? do
5
+ if !defined?(@sequential_updates)
6
+ if sequential_updates_option.nil?
7
+ table_exists = caller_class.connection.table_exists?(caller_class.table_name)
8
+ index_exists = caller_class.connection.index_exists?(caller_class.table_name, column, unique: true)
9
+ @sequential_updates = table_exists && index_exists
10
+ else
11
+ @sequential_updates = sequential_updates_option
12
+ end
13
+ else
14
+ @sequential_updates
15
+ end
16
+ end
17
+
18
+ private :sequential_updates?
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ module ActiveRecord::Acts::List::TopOfListMethodDefiner #:nodoc:
2
+ def self.call(caller_class, top_of_list)
3
+ caller_class.class_eval do
4
+ define_singleton_method :acts_as_list_top do
5
+ top_of_list.to_i
6
+ end
7
+
8
+ define_method :acts_as_list_top do
9
+ top_of_list.to_i
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,7 +1,7 @@
1
1
  module ActiveRecord
2
2
  module Acts
3
3
  module List
4
- VERSION = '0.7.4'
4
+ VERSION = '0.9.0'
5
5
  end
6
6
  end
7
7
  end
data/lib/acts_as_list.rb CHANGED
@@ -1,15 +1,9 @@
1
1
  require 'acts_as_list/active_record/acts/list'
2
-
3
- module ActsAsList
4
- if defined?(Rails::Railtie)
5
- class Railtie < Rails::Railtie
6
- initializer 'acts_as_list.insert_into_active_record' do
7
- ActiveSupport.on_load :active_record do
8
- ActiveRecord::Base.send(:include, ActiveRecord::Acts::List)
9
- end
10
- end
11
- end
12
- else
13
- ActiveRecord::Base.send(:include, ActiveRecord::Acts::List) if defined?(ActiveRecord)
14
- end
15
- end
2
+ require "acts_as_list/active_record/acts/column_method_definer"
3
+ require "acts_as_list/active_record/acts/scope_method_definer"
4
+ require "acts_as_list/active_record/acts/top_of_list_method_definer"
5
+ require "acts_as_list/active_record/acts/add_new_at_method_definer"
6
+ require "acts_as_list/active_record/acts/aux_method_definer"
7
+ require "acts_as_list/active_record/acts/callback_definer"
8
+ require 'acts_as_list/active_record/acts/no_update'
9
+ require "acts_as_list/active_record/acts/sequential_updates_method_definer"
data/test/database.yml ADDED
@@ -0,0 +1,16 @@
1
+ sqlite:
2
+ adapter: sqlite3
3
+ database: "file:memdb1?mode=memory&cache=shared"
4
+
5
+ mysql:
6
+ adapter: mysql2
7
+ username: root
8
+ password:
9
+ database: acts_as_list
10
+
11
+ postgresql:
12
+ adapter: postgresql
13
+ username: postgres
14
+ password:
15
+ database: acts_as_list
16
+ min_messages: ERROR
data/test/helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # $DEBUG = true
2
+
1
3
  require "rubygems"
2
4
  require "bundler/setup"
3
5
  begin
@@ -12,10 +14,20 @@ require "minitest/autorun"
12
14
  require "#{File.dirname(__FILE__)}/../init"
13
15
 
14
16
  if defined?(ActiveRecord::VERSION) &&
15
- ActiveRecord::VERSION::MAJOR > 4 ||
16
- (ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR >= 2)
17
+ ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR >= 2
17
18
 
19
+ # Was removed in Rails 5 and is effectively true.
18
20
  ActiveRecord::Base.raise_in_transactional_callbacks = true
19
21
  end
20
22
 
21
23
  require "shared"
24
+
25
+ # ActiveRecord::Base.logger = Logger.new(STDOUT)
26
+
27
+ def assert_equal_or_nil(a, b)
28
+ if a.nil?
29
+ assert_nil b
30
+ else
31
+ assert_equal a, b
32
+ end
33
+ end
data/test/shared.rb CHANGED
@@ -6,4 +6,5 @@ module Shared
6
6
  autoload :ArrayScopeList, 'shared_array_scope_list'
7
7
  autoload :TopAddition, 'shared_top_addition'
8
8
  autoload :NoAddition, 'shared_no_addition'
9
+ autoload :Quoting, 'shared_quoting'
9
10
  end
@@ -25,7 +25,7 @@ module Shared
25
25
 
26
26
  ArrayScopeListMixin.where(id: 4).first.move_to_top
27
27
  assert_equal [4, 1, 3, 2], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
28
-
28
+
29
29
  ArrayScopeListMixin.where(id: 4).first.insert_at(4)
30
30
  assert_equal [1, 3, 2, 4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
31
31
  assert_equal [1, 2, 3, 4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:pos)
@@ -60,6 +60,11 @@ module Shared
60
60
  assert !new.first?
61
61
  assert new.last?
62
62
 
63
+ new = ArrayScopeListMixin.acts_as_list_no_update { ArrayScopeListMixin.create(parent_id: 20, parent_type: 'ParentClass') }
64
+ assert_equal_or_nil $default_position,new.pos
65
+ assert_equal $default_position.is_a?(Fixnum), new.first?
66
+ assert !new.last?
67
+
63
68
  new = ArrayScopeListMixin.create(parent_id: 20, parent_type: 'ParentClass')
64
69
  assert_equal 3, new.pos
65
70
  assert !new.first?
@@ -81,6 +86,9 @@ module Shared
81
86
  new = ArrayScopeListMixin.create(parent_id: 20, parent_type: 'ParentClass')
82
87
  assert_equal 3, new.pos
83
88
 
89
+ new_noup = ArrayScopeListMixin.acts_as_list_no_update { ArrayScopeListMixin.create(parent_id: 20, parent_type: 'ParentClass') }
90
+ assert_equal_or_nil $default_position,new_noup.pos
91
+
84
92
  new4 = ArrayScopeListMixin.create(parent_id: 20, parent_type: 'ParentClass')
85
93
  assert_equal 4, new4.pos
86
94
 
@@ -104,6 +112,9 @@ module Shared
104
112
 
105
113
  new4.reload
106
114
  assert_equal 5, new4.pos
115
+
116
+ new_noup.reload
117
+ assert_equal_or_nil $default_position, new_noup.pos
107
118
  end
108
119
 
109
120
  def test_delete_middle
@@ -123,6 +134,12 @@ module Shared
123
134
 
124
135
  assert_equal 1, ArrayScopeListMixin.where(id: 3).first.pos
125
136
  assert_equal 2, ArrayScopeListMixin.where(id: 4).first.pos
137
+
138
+ ArrayScopeListMixin.acts_as_list_no_update { ArrayScopeListMixin.where(id: 3).first.destroy }
139
+
140
+ assert_equal [4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
141
+
142
+ assert_equal 2, ArrayScopeListMixin.where(id: 4).first.pos
126
143
  end
127
144
 
128
145
  def test_remove_from_list_should_then_fail_in_list?
@@ -136,10 +153,8 @@ module Shared
136
153
 
137
154
  ArrayScopeListMixin.where(id: 2).first.remove_from_list
138
155
 
139
- assert_equal [2, 1, 3, 4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
140
-
141
156
  assert_equal 1, ArrayScopeListMixin.where(id: 1).first.pos
142
- assert_equal nil, ArrayScopeListMixin.where(id: 2).first.pos
157
+ assert_nil ArrayScopeListMixin.where(id: 2).first.pos
143
158
  assert_equal 2, ArrayScopeListMixin.where(id: 3).first.pos
144
159
  assert_equal 3, ArrayScopeListMixin.where(id: 4).first.pos
145
160
  end
data/test/shared_list.rb CHANGED
@@ -60,6 +60,11 @@ module Shared
60
60
  assert !new.first?
61
61
  assert new.last?
62
62
 
63
+ new = ListMixin.acts_as_list_no_update { ListMixin.create(parent_id: 20) }
64
+ assert_equal_or_nil $default_position, new.pos
65
+ assert_equal $default_position.is_a?(Fixnum), new.first?
66
+ assert !new.last?
67
+
63
68
  new = ListMixin.create(parent_id: 20)
64
69
  assert_equal 3, new.pos
65
70
  assert !new.first?
@@ -81,6 +86,9 @@ module Shared
81
86
  new = ListMixin.create(parent_id: 20)
82
87
  assert_equal 3, new.pos
83
88
 
89
+ new_noup = ListMixin.acts_as_list_no_update { ListMixin.create(parent_id: 20) }
90
+ assert_equal_or_nil $default_position, new_noup.pos
91
+
84
92
  new4 = ListMixin.create(parent_id: 20)
85
93
  assert_equal 4, new4.pos
86
94
 
@@ -104,13 +112,21 @@ module Shared
104
112
 
105
113
  new4.reload
106
114
  assert_equal 5, new4.pos
115
+
116
+ new_noup.reload
117
+ assert_equal_or_nil $default_position, new_noup.pos
118
+
119
+ last1 = ListMixin.where('pos IS NOT NULL').order('pos').last
120
+ last2 = ListMixin.where('pos IS NOT NULL').order('pos').last
121
+ last1.insert_at(1)
122
+ last2.insert_at(1)
123
+ pos_list = ListMixin.where(parent_id: 20).order("pos ASC#{' NULLS FIRST' if ENV['DB'] == 'postgresql'}").map(&:pos)
124
+ assert_equal [$default_position, 1, 2, 3, 4, 5], pos_list
107
125
  end
108
126
 
109
127
  def test_delete_middle
110
128
  assert_equal [1, 2, 3, 4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
111
129
 
112
-
113
-
114
130
  ListMixin.where(id: 2).first.destroy
115
131
 
116
132
  assert_equal [1, 3, 4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
@@ -125,6 +141,12 @@ module Shared
125
141
 
126
142
  assert_equal 1, ListMixin.where(id: 3).first.pos
127
143
  assert_equal 2, ListMixin.where(id: 4).first.pos
144
+
145
+ ListMixin.acts_as_list_no_update { ListMixin.where(id: 3).first.destroy }
146
+
147
+ assert_equal [4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
148
+
149
+ assert_equal 2, ListMixin.where(id: 4).first.pos
128
150
  end
129
151
 
130
152
  def test_with_string_based_scope
@@ -142,7 +164,7 @@ module Shared
142
164
 
143
165
  def test_update_position_when_scope_changes
144
166
  assert_equal [1, 2, 3, 4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
145
- parent = ListMixin.create(parent_id: 6)
167
+ ListMixin.create(parent_id: 6)
146
168
 
147
169
  ListMixin.where(id: 2).first.move_within_scope(6)
148
170
 
@@ -169,10 +191,8 @@ module Shared
169
191
 
170
192
  ListMixin.where(id: 2).first.remove_from_list
171
193
 
172
- assert_equal [2, 1, 3, 4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
173
-
174
194
  assert_equal 1, ListMixin.where(id: 1).first.pos
175
- assert_equal nil, ListMixin.where(id: 2).first.pos
195
+ assert_nil ListMixin.where(id: 2).first.pos
176
196
  assert_equal 2, ListMixin.where(id: 3).first.pos
177
197
  assert_equal 3, ListMixin.where(id: 4).first.pos
178
198
  end
@@ -237,14 +257,30 @@ module Shared
237
257
 
238
258
  assert_equal [5, 1, 2, 3, 4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
239
259
 
260
+ new6 = ListMixin.new(parent_id: 5)
261
+ new6.pos = 3
262
+ new6.save!
263
+ assert_equal 3, new6.pos
264
+ assert !new6.first?
265
+ assert !new6.last?
266
+
267
+ assert_equal [5, 1, 6, 2, 3, 4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
268
+
240
269
  new = ListMixin.new(parent_id: 5)
241
270
  new.pos = 3
242
- new.save!
271
+ ListMixin.acts_as_list_no_update { new.save! }
243
272
  assert_equal 3, new.pos
273
+ assert_equal 3, new6.pos
244
274
  assert !new.first?
245
275
  assert !new.last?
246
276
 
247
- assert_equal [5, 1, 6, 2, 3, 4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
277
+ assert_equal [5, 1, 6, 7, 2, 3, 4], ListMixin.where(parent_id: 5).order('pos, id').map(&:id)
278
+ end
279
+
280
+ def test_non_persisted_records_dont_get_lock_called
281
+ new = ListMixin.new(parent_id: 5)
282
+
283
+ new.destroy
248
284
  end
249
285
  end
250
286
  end
@@ -43,6 +43,36 @@ module Shared
43
43
  assert_nil ListMixin.where(id: 4).first.lower_item
44
44
  end
45
45
 
46
+ def test_next_prev_not_regular_sequence
47
+ ListMixin.all.each do |item|
48
+ item.update_attributes(pos: item.pos * 5)
49
+ end
50
+
51
+ assert_equal [1, 2, 3, 4], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
52
+ assert_equal [5, 10, 15, 20], ListMixin.where(parent_id: 5000).order('id').map(&:pos)
53
+
54
+ ListMixin.where(id: 2).first.move_lower
55
+ assert_equal [1, 3, 2, 4], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
56
+ assert_equal [5, 15, 10, 20], ListMixin.where(parent_id: 5000).order('id').map(&:pos)
57
+
58
+
59
+ ListMixin.where(id: 2).first.move_higher
60
+ assert_equal [1, 2, 3, 4], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
61
+ assert_equal [5, 10, 15, 20], ListMixin.where(parent_id: 5000).order('id').map(&:pos)
62
+
63
+ ListMixin.where(id: 1).first.move_to_bottom
64
+ assert_equal [2, 3, 4, 1], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
65
+
66
+ ListMixin.where(id: 1).first.move_to_top
67
+ assert_equal [1, 2, 3, 4], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
68
+
69
+ ListMixin.where(id: 2).first.move_to_bottom
70
+ assert_equal [1, 3, 4, 2], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
71
+
72
+ ListMixin.where(id: 4).first.move_to_top
73
+ assert_equal [4, 1, 3, 2], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
74
+ end
75
+
46
76
  def test_next_prev_groups
47
77
  li1 = ListMixin.where(id: 1).first
48
78
  li2 = ListMixin.where(id: 2).first
@@ -53,12 +83,29 @@ module Shared
53
83
  assert_equal [li2, li3], li1.lower_items(2)
54
84
  assert_equal [], li4.lower_items
55
85
 
56
- assert_equal [li1, li2], li3.higher_items
86
+ assert_equal [li2, li1], li3.higher_items
57
87
  assert_equal [li1], li2.higher_items
58
- assert_equal [li2, li3], li4.higher_items(2)
88
+ assert_equal [li3, li2], li4.higher_items(2)
59
89
  assert_equal [], li1.higher_items
60
90
  end
61
91
 
92
+ def test_next_prev_groups_with_same_position
93
+ li1 = ListMixin.where(id: 1).first
94
+ li2 = ListMixin.where(id: 2).first
95
+ li3 = ListMixin.where(id: 3).first
96
+ li4 = ListMixin.where(id: 4).first
97
+
98
+ li3.update_column(:pos, 2) # Make the same position as li2
99
+
100
+ assert_equal [1, 2, 2, 4], ListMixin.order(:pos).pluck(:pos)
101
+
102
+ assert_equal [li3, li4], li2.lower_items
103
+ assert_equal [li2, li4], li3.lower_items
104
+
105
+ assert_equal [li3, li1], li2.higher_items
106
+ assert_equal [li2, li1], li3.higher_items
107
+ end
108
+
62
109
  def test_injection
63
110
  item = ListMixin.new("parent_id"=>1)
64
111
  assert_equal({ parent_id: 1 }, item.scope_condition)
@@ -75,6 +122,9 @@ module Shared
75
122
  new = ListMixinSub1.create("parent_id" => 20)
76
123
  assert_equal 3, new.pos
77
124
 
125
+ new_noup = ListMixinSub1.acts_as_list_no_update { ListMixinSub1.create("parent_id" => 20) }
126
+ assert_equal_or_nil $default_position, new_noup.pos
127
+
78
128
  new4 = ListMixin.create("parent_id" => 20)
79
129
  assert_equal 4, new4.pos
80
130
 
@@ -98,6 +148,9 @@ module Shared
98
148
 
99
149
  new4.reload
100
150
  assert_equal 5, new4.pos
151
+
152
+ new_noup.reload
153
+ assert_equal_or_nil $default_position, new_noup.pos
101
154
  end
102
155
 
103
156
  def test_delete_middle
@@ -117,6 +170,12 @@ module Shared
117
170
 
118
171
  assert_equal 1, ListMixin.where(id: 3).first.pos
119
172
  assert_equal 2, ListMixin.where(id: 4).first.pos
173
+
174
+ ListMixin.acts_as_list_no_update { ListMixin.where(id: 3).first.destroy }
175
+
176
+ assert_equal [4], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
177
+
178
+ assert_equal 2, ListMixin.where(id: 4).first.pos
120
179
  end
121
180
 
122
181
  def test_acts_as_list_class
@@ -6,11 +6,11 @@ module Shared
6
6
 
7
7
  def test_insert
8
8
  new = NoAdditionMixin.create(parent_id: 20)
9
- assert_equal nil, new.pos
9
+ assert_nil new.pos
10
10
  assert !new.in_list?
11
11
 
12
12
  new = NoAdditionMixin.create(parent_id: 20)
13
- assert_equal nil, new.pos
13
+ assert_nil new.pos
14
14
  end
15
15
 
16
16
  def test_update_does_not_add_to_list
@@ -21,5 +21,16 @@ module Shared
21
21
  assert !new.in_list?
22
22
  end
23
23
 
24
+ def test_update_scope_does_not_add_to_list
25
+ new = NoAdditionMixin.create
26
+
27
+ new.update_attribute(:parent_id, 20)
28
+ new.reload
29
+ assert !new.in_list?
30
+
31
+ new.update_attribute(:parent_id, 5)
32
+ new.reload
33
+ assert !new.in_list?
34
+ end
24
35
  end
25
36
  end
@@ -0,0 +1,21 @@
1
+ module Shared
2
+ module Quoting
3
+
4
+ def setup
5
+ 3.times { |counter| QuotedList.create! order: counter }
6
+ end
7
+
8
+ def test_create
9
+ assert_equal QuotedList.in_list.size, 3
10
+ end
11
+
12
+ # This test execute raw queries involving table name
13
+ def test_moving
14
+ item = QuotedList.first
15
+ item.higher_items
16
+ item.lower_items
17
+ item.send :bottom_item # Part of private api
18
+ end
19
+
20
+ end
21
+ end
@@ -4,23 +4,26 @@ module Shared
4
4
  (1..4).each { |counter| TopAdditionMixin.create! pos: counter, parent_id: 5 }
5
5
  end
6
6
 
7
- def test_reordering
8
- assert_equal [4, 3, 2, 1], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
7
+ def test_setup_state
8
+ # If we explicitly define a position (as above) then that position is what gets applied
9
+ assert_equal [1, 2, 3, 4], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
10
+ end
9
11
 
12
+ def test_reordering
10
13
  TopAdditionMixin.where(id: 2).first.move_lower
11
- assert_equal [4, 3, 1, 2], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
14
+ assert_equal [1, 3, 2, 4], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
12
15
 
13
16
  TopAdditionMixin.where(id: 2).first.move_higher
14
- assert_equal [4, 3, 2, 1], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
17
+ assert_equal [1, 2, 3, 4], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
15
18
 
16
19
  TopAdditionMixin.where(id: 1).first.move_to_bottom
17
- assert_equal [4, 3, 2, 1], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
20
+ assert_equal [2, 3, 4, 1], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
18
21
 
19
22
  TopAdditionMixin.where(id: 1).first.move_to_top
20
- assert_equal [1, 4, 3, 2], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
23
+ assert_equal [1, 2, 3, 4], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
21
24
 
22
25
  TopAdditionMixin.where(id: 2).first.move_to_bottom
23
- assert_equal [1, 4, 3, 2], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
26
+ assert_equal [1, 3, 4, 2], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
24
27
 
25
28
  TopAdditionMixin.where(id: 4).first.move_to_top
26
29
  assert_equal [4, 1, 3, 2], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
@@ -43,9 +46,14 @@ module Shared
43
46
  assert new.first?
44
47
  assert !new.last?
45
48
 
49
+ new = TopAdditionMixin.acts_as_list_no_update { TopAdditionMixin.create(parent_id: 20) }
50
+ assert_equal_or_nil $default_position, new.pos
51
+ assert_equal $default_position.is_a?(Fixnum), new.first?
52
+ assert !new.last?
53
+
46
54
  new = TopAdditionMixin.create(parent_id: 20)
47
55
  assert_equal 1, new.pos
48
- assert new.first?
56
+ assert_equal $default_position.nil?, new.first?
49
57
  assert !new.last?
50
58
 
51
59
  new = TopAdditionMixin.create(parent_id: 0)
@@ -64,6 +72,9 @@ module Shared
64
72
  new = TopAdditionMixin.create(parent_id: 20)
65
73
  assert_equal 1, new.pos
66
74
 
75
+ new = TopAdditionMixin.acts_as_list_no_update { TopAdditionMixin.create(parent_id: 20) }
76
+ assert_equal_or_nil $default_position, new.pos
77
+
67
78
  new4 = TopAdditionMixin.create(parent_id: 20)
68
79
  assert_equal 1, new4.pos
69
80
 
@@ -71,16 +82,26 @@ module Shared
71
82
  assert_equal 3, new4.pos
72
83
  end
73
84
 
74
- def test_delete_middle
75
- assert_equal [4, 3, 2, 1], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
85
+ def test_supplied_position
86
+ new = TopAdditionMixin.create(parent_id: 20, pos: 3)
87
+ assert_equal 3, new.pos
88
+ end
76
89
 
90
+ def test_delete_middle
77
91
  TopAdditionMixin.where(id: 2).first.destroy
78
92
 
79
- assert_equal [4, 3, 1], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
93
+ assert_equal [1, 3, 4], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
80
94
 
81
- assert_equal 3, TopAdditionMixin.where(id: 1).first.pos
95
+ assert_equal 1, TopAdditionMixin.where(id: 1).first.pos
82
96
  assert_equal 2, TopAdditionMixin.where(id: 3).first.pos
83
- assert_equal 1, TopAdditionMixin.where(id: 4).first.pos
97
+ assert_equal 3, TopAdditionMixin.where(id: 4).first.pos
98
+
99
+ TopAdditionMixin.acts_as_list_no_update { TopAdditionMixin.where(id: 3).first.destroy }
100
+
101
+ assert_equal [1, 4], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
102
+
103
+ assert_equal 1, TopAdditionMixin.where(id: 1).first.pos
104
+ assert_equal 3, TopAdditionMixin.where(id: 4).first.pos
84
105
  end
85
106
 
86
107
  end
@@ -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