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.
- checksums.yaml +5 -13
- data/.gitignore +1 -0
- data/.travis.yml +23 -3
- data/Appraisals +13 -3
- data/CHANGELOG.md +131 -2
- data/Gemfile +18 -11
- data/README.md +49 -6
- data/gemfiles/rails_3_2.gemfile +16 -7
- data/gemfiles/rails_4_1.gemfile +16 -7
- data/gemfiles/rails_4_2.gemfile +16 -7
- data/gemfiles/rails_5_0.gemfile +32 -0
- data/lib/acts_as_list/active_record/acts/add_new_at_method_definer.rb +9 -0
- data/lib/acts_as_list/active_record/acts/aux_method_definer.rb +9 -0
- data/lib/acts_as_list/active_record/acts/callback_definer.rb +19 -0
- data/lib/acts_as_list/active_record/acts/column_method_definer.rb +50 -0
- data/lib/acts_as_list/active_record/acts/list.rb +247 -291
- data/lib/acts_as_list/active_record/acts/no_update.rb +50 -0
- data/lib/acts_as_list/active_record/acts/scope_method_definer.rb +49 -0
- data/lib/acts_as_list/active_record/acts/sequential_updates_method_definer.rb +21 -0
- data/lib/acts_as_list/active_record/acts/top_of_list_method_definer.rb +13 -0
- data/lib/acts_as_list/version.rb +1 -1
- data/lib/acts_as_list.rb +8 -14
- data/test/database.yml +16 -0
- data/test/helper.rb +14 -2
- data/test/shared.rb +1 -0
- data/test/shared_array_scope_list.rb +19 -4
- data/test/shared_list.rb +44 -8
- data/test/shared_list_sub.rb +61 -2
- data/test/shared_no_addition.rb +13 -2
- data/test/shared_quoting.rb +21 -0
- data/test/shared_top_addition.rb +34 -13
- data/test/shared_zero_based.rb +11 -0
- data/test/test_joined_list.rb +70 -0
- data/test/test_list.rb +307 -28
- metadata +26 -11
@@ -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
|
data/lib/acts_as_list/version.rb
CHANGED
data/lib/acts_as_list.rb
CHANGED
@@ -1,15 +1,9 @@
|
|
1
1
|
require 'acts_as_list/active_record/acts/list'
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
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
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/test/shared_list_sub.rb
CHANGED
@@ -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 [
|
86
|
+
assert_equal [li2, li1], li3.higher_items
|
57
87
|
assert_equal [li1], li2.higher_items
|
58
|
-
assert_equal [
|
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
|
data/test/shared_no_addition.rb
CHANGED
@@ -6,11 +6,11 @@ module Shared
|
|
6
6
|
|
7
7
|
def test_insert
|
8
8
|
new = NoAdditionMixin.create(parent_id: 20)
|
9
|
-
|
9
|
+
assert_nil new.pos
|
10
10
|
assert !new.in_list?
|
11
11
|
|
12
12
|
new = NoAdditionMixin.create(parent_id: 20)
|
13
|
-
|
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
|
data/test/shared_top_addition.rb
CHANGED
@@ -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
|
8
|
-
|
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 [
|
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 [
|
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 [
|
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,
|
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,
|
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
|
-
|
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
|
75
|
-
|
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 [
|
93
|
+
assert_equal [1, 3, 4], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
|
80
94
|
|
81
|
-
assert_equal
|
95
|
+
assert_equal 1, TopAdditionMixin.where(id: 1).first.pos
|
82
96
|
assert_equal 2, TopAdditionMixin.where(id: 3).first.pos
|
83
|
-
assert_equal
|
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
|
data/test/shared_zero_based.rb
CHANGED
@@ -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
|