acts_as_list 0.7.4 → 1.1.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/.github/FUNDING.yml +3 -0
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/ci.yml +123 -0
- data/.gitignore +1 -0
- data/.travis.yml +50 -12
- data/Appraisals +39 -6
- data/CHANGELOG.md +565 -148
- data/Gemfile +19 -14
- data/README.md +206 -19
- data/Rakefile +4 -4
- data/acts_as_list.gemspec +16 -11
- data/gemfiles/rails_4_2.gemfile +18 -9
- data/gemfiles/rails_5_0.gemfile +31 -0
- data/gemfiles/rails_5_1.gemfile +31 -0
- data/gemfiles/rails_5_2.gemfile +31 -0
- data/gemfiles/rails_6_0.gemfile +31 -0
- data/gemfiles/rails_6_1.gemfile +31 -0
- data/gemfiles/rails_7_0.gemfile +31 -0
- data/init.rb +2 -0
- data/lib/acts_as_list/active_record/acts/active_record.rb +5 -0
- data/lib/acts_as_list/active_record/acts/add_new_at_method_definer.rb +11 -0
- data/lib/acts_as_list/active_record/acts/aux_method_definer.rb +11 -0
- data/lib/acts_as_list/active_record/acts/callback_definer.rb +19 -0
- data/lib/acts_as_list/active_record/acts/list.rb +299 -306
- data/lib/acts_as_list/active_record/acts/no_update.rb +125 -0
- data/lib/acts_as_list/active_record/acts/position_column_method_definer.rb +101 -0
- data/lib/acts_as_list/active_record/acts/scope_method_definer.rb +77 -0
- data/lib/acts_as_list/active_record/acts/sequential_updates_method_definer.rb +28 -0
- data/lib/acts_as_list/active_record/acts/top_of_list_method_definer.rb +15 -0
- data/lib/acts_as_list/version.rb +3 -1
- data/lib/acts_as_list.rb +11 -14
- data/test/database.yml +18 -0
- data/test/helper.rb +50 -2
- data/test/shared.rb +3 -0
- data/test/shared_array_scope_list.rb +21 -4
- data/test/shared_list.rb +86 -12
- data/test/shared_list_sub.rb +63 -2
- data/test/shared_no_addition.rb +50 -2
- data/test/shared_quoting.rb +23 -0
- data/test/shared_top_addition.rb +36 -13
- data/test/shared_zero_based.rb +13 -0
- data/test/test_default_scope_with_select.rb +33 -0
- data/test/test_joined_list.rb +61 -0
- data/test/test_list.rb +601 -84
- data/test/test_no_update_for_extra_classes.rb +131 -0
- data/test/test_no_update_for_scope_destruction.rb +69 -0
- data/test/test_no_update_for_subclasses.rb +56 -0
- data/test/test_scope_with_user_defined_foreign_key.rb +42 -0
- metadata +56 -22
- data/gemfiles/rails_3_2.gemfile +0 -24
- data/gemfiles/rails_4_1.gemfile +0 -24
data/test/shared_list.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Shared
|
2
4
|
module List
|
3
5
|
def setup
|
@@ -8,6 +10,13 @@ module Shared
|
|
8
10
|
end
|
9
11
|
end
|
10
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
|
+
|
11
20
|
def test_reordering
|
12
21
|
assert_equal [1, 2, 3, 4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
|
13
22
|
|
@@ -60,6 +69,11 @@ module Shared
|
|
60
69
|
assert !new.first?
|
61
70
|
assert new.last?
|
62
71
|
|
72
|
+
new = ListMixin.acts_as_list_no_update { ListMixin.create(parent_id: 20) }
|
73
|
+
assert_equal_or_nil $default_position, new.pos
|
74
|
+
assert_equal $default_position.is_a?(Integer), new.first?
|
75
|
+
assert !new.last?
|
76
|
+
|
63
77
|
new = ListMixin.create(parent_id: 20)
|
64
78
|
assert_equal 3, new.pos
|
65
79
|
assert !new.first?
|
@@ -81,6 +95,9 @@ module Shared
|
|
81
95
|
new = ListMixin.create(parent_id: 20)
|
82
96
|
assert_equal 3, new.pos
|
83
97
|
|
98
|
+
new_noup = ListMixin.acts_as_list_no_update { ListMixin.create(parent_id: 20) }
|
99
|
+
assert_equal_or_nil $default_position, new_noup.pos
|
100
|
+
|
84
101
|
new4 = ListMixin.create(parent_id: 20)
|
85
102
|
assert_equal 4, new4.pos
|
86
103
|
|
@@ -104,12 +121,32 @@ module Shared
|
|
104
121
|
|
105
122
|
new4.reload
|
106
123
|
assert_equal 5, new4.pos
|
124
|
+
|
125
|
+
new_noup.reload
|
126
|
+
assert_equal_or_nil $default_position, new_noup.pos
|
127
|
+
|
128
|
+
last1 = ListMixin.where('pos IS NOT NULL').order('pos').last
|
129
|
+
last2 = ListMixin.where('pos IS NOT NULL').order('pos').last
|
130
|
+
last1.insert_at(1)
|
131
|
+
last2.insert_at(1)
|
132
|
+
pos_list = ListMixin.where(parent_id: 20).order("pos ASC#{' NULLS FIRST' if ENV['DB'] == 'postgresql'}").map(&:pos)
|
133
|
+
assert_equal [$default_position, 1, 2, 3, 4, 5], pos_list
|
107
134
|
end
|
108
135
|
|
109
|
-
def
|
110
|
-
|
136
|
+
def test_insert_at_after_dup
|
137
|
+
new1 = ListMixin.create(parent_id: 20)
|
138
|
+
new2 = ListMixin.create(parent_id: 20)
|
139
|
+
new3 = ListMixin.create(parent_id: 20)
|
140
|
+
|
141
|
+
duped = new1.dup
|
142
|
+
duped.save
|
143
|
+
[new1, new2, new3, duped].map(&:reload)
|
111
144
|
|
145
|
+
assert_equal [1, 2, 3, 4], [duped.pos, new1.pos, new2.pos, new3.pos]
|
146
|
+
end
|
112
147
|
|
148
|
+
def test_delete_middle
|
149
|
+
assert_equal [1, 2, 3, 4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
|
113
150
|
|
114
151
|
ListMixin.where(id: 2).first.destroy
|
115
152
|
|
@@ -125,6 +162,12 @@ module Shared
|
|
125
162
|
|
126
163
|
assert_equal 1, ListMixin.where(id: 3).first.pos
|
127
164
|
assert_equal 2, ListMixin.where(id: 4).first.pos
|
165
|
+
|
166
|
+
ListMixin.acts_as_list_no_update { ListMixin.where(id: 3).first.destroy }
|
167
|
+
|
168
|
+
assert_equal [4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
|
169
|
+
|
170
|
+
assert_equal 2, ListMixin.where(id: 4).first.pos
|
128
171
|
end
|
129
172
|
|
130
173
|
def test_with_string_based_scope
|
@@ -142,7 +185,7 @@ module Shared
|
|
142
185
|
|
143
186
|
def test_update_position_when_scope_changes
|
144
187
|
assert_equal [1, 2, 3, 4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
|
145
|
-
|
188
|
+
ListMixin.create(parent_id: 6)
|
146
189
|
|
147
190
|
ListMixin.where(id: 2).first.move_within_scope(6)
|
148
191
|
|
@@ -169,10 +212,8 @@ module Shared
|
|
169
212
|
|
170
213
|
ListMixin.where(id: 2).first.remove_from_list
|
171
214
|
|
172
|
-
assert_equal [2, 1, 3, 4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
|
173
|
-
|
174
215
|
assert_equal 1, ListMixin.where(id: 1).first.pos
|
175
|
-
|
216
|
+
assert_nil ListMixin.where(id: 2).first.pos
|
176
217
|
assert_equal 2, ListMixin.where(id: 3).first.pos
|
177
218
|
assert_equal 3, ListMixin.where(id: 4).first.pos
|
178
219
|
end
|
@@ -196,12 +237,9 @@ module Shared
|
|
196
237
|
# We need to trigger all the before_destroy callbacks without actually
|
197
238
|
# destroying the record so we can see the affect the callbacks have on
|
198
239
|
# the record.
|
199
|
-
# NOTE: Hotfix for rails3 ActiveRecord
|
200
240
|
list = ListMixin.where(id: 2).first
|
201
241
|
if list.respond_to?(:run_callbacks)
|
202
|
-
|
203
|
-
list.run_callbacks(:destroy) if rails_3
|
204
|
-
list.run_callbacks(:before_destroy) if !rails_3
|
242
|
+
list.run_callbacks(:destroy)
|
205
243
|
else
|
206
244
|
list.send(:callback, :before_destroy)
|
207
245
|
end
|
@@ -237,14 +275,50 @@ module Shared
|
|
237
275
|
|
238
276
|
assert_equal [5, 1, 2, 3, 4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
|
239
277
|
|
278
|
+
new6 = ListMixin.new(parent_id: 5)
|
279
|
+
new6.pos = 3
|
280
|
+
new6.save!
|
281
|
+
assert_equal 3, new6.pos
|
282
|
+
assert !new6.first?
|
283
|
+
assert !new6.last?
|
284
|
+
|
285
|
+
assert_equal [5, 1, 6, 2, 3, 4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
|
286
|
+
|
240
287
|
new = ListMixin.new(parent_id: 5)
|
241
288
|
new.pos = 3
|
242
|
-
new.save!
|
289
|
+
ListMixin.acts_as_list_no_update { new.save! }
|
243
290
|
assert_equal 3, new.pos
|
291
|
+
assert_equal 3, new6.pos
|
244
292
|
assert !new.first?
|
245
293
|
assert !new.last?
|
246
294
|
|
247
|
-
assert_equal [5, 1, 6, 2, 3, 4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
|
295
|
+
assert_equal [5, 1, 6, 7, 2, 3, 4], ListMixin.where(parent_id: 5).order('pos, id').map(&:id)
|
296
|
+
end
|
297
|
+
|
298
|
+
def test_non_persisted_records_dont_get_lock_called
|
299
|
+
new = ListMixin.new(parent_id: 5)
|
300
|
+
new.destroy
|
301
|
+
end
|
302
|
+
|
303
|
+
def test_invalid_records_dont_get_inserted
|
304
|
+
new = ListMixinError.new(parent_id: 5, state: nil)
|
305
|
+
assert !new.valid?
|
306
|
+
new.insert_at(1)
|
307
|
+
assert !new.persisted?
|
308
|
+
end
|
309
|
+
|
310
|
+
def test_invalid_records_raise_error_with_insert_at!
|
311
|
+
new = ListMixinError.new(parent_id: 5, state: nil)
|
312
|
+
assert !new.valid?
|
313
|
+
assert_raises ActiveRecord::RecordInvalid do
|
314
|
+
new.insert_at!(1)
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
def test_find_or_create_doesnt_raise_deprecation_warning
|
319
|
+
assert_no_deprecation_warning_raised_by('ActiveRecord deprecation warning raised when using `find_or_create_by` when we didn\'t expect it') do
|
320
|
+
ListMixin.where(parent_id: 5).find_or_create_by(pos: 5)
|
321
|
+
end
|
248
322
|
end
|
249
323
|
end
|
250
324
|
end
|
data/test/shared_list_sub.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Shared
|
2
4
|
module ListSub
|
3
5
|
def setup
|
@@ -43,6 +45,36 @@ module Shared
|
|
43
45
|
assert_nil ListMixin.where(id: 4).first.lower_item
|
44
46
|
end
|
45
47
|
|
48
|
+
def test_next_prev_not_regular_sequence
|
49
|
+
ListMixin.all.each do |item|
|
50
|
+
item.update pos: item.pos * 5
|
51
|
+
end
|
52
|
+
|
53
|
+
assert_equal [1, 2, 3, 4], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
|
54
|
+
assert_equal [5, 10, 15, 20], ListMixin.where(parent_id: 5000).order('id').map(&:pos)
|
55
|
+
|
56
|
+
ListMixin.where(id: 2).first.move_lower
|
57
|
+
assert_equal [1, 3, 2, 4], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
|
58
|
+
assert_equal [5, 15, 10, 20], ListMixin.where(parent_id: 5000).order('id').map(&:pos)
|
59
|
+
|
60
|
+
|
61
|
+
ListMixin.where(id: 2).first.move_higher
|
62
|
+
assert_equal [1, 2, 3, 4], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
|
63
|
+
assert_equal [5, 10, 15, 20], ListMixin.where(parent_id: 5000).order('id').map(&:pos)
|
64
|
+
|
65
|
+
ListMixin.where(id: 1).first.move_to_bottom
|
66
|
+
assert_equal [2, 3, 4, 1], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
|
67
|
+
|
68
|
+
ListMixin.where(id: 1).first.move_to_top
|
69
|
+
assert_equal [1, 2, 3, 4], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
|
70
|
+
|
71
|
+
ListMixin.where(id: 2).first.move_to_bottom
|
72
|
+
assert_equal [1, 3, 4, 2], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
|
73
|
+
|
74
|
+
ListMixin.where(id: 4).first.move_to_top
|
75
|
+
assert_equal [4, 1, 3, 2], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
|
76
|
+
end
|
77
|
+
|
46
78
|
def test_next_prev_groups
|
47
79
|
li1 = ListMixin.where(id: 1).first
|
48
80
|
li2 = ListMixin.where(id: 2).first
|
@@ -53,12 +85,29 @@ module Shared
|
|
53
85
|
assert_equal [li2, li3], li1.lower_items(2)
|
54
86
|
assert_equal [], li4.lower_items
|
55
87
|
|
56
|
-
assert_equal [
|
88
|
+
assert_equal [li2, li1], li3.higher_items
|
57
89
|
assert_equal [li1], li2.higher_items
|
58
|
-
assert_equal [
|
90
|
+
assert_equal [li3, li2], li4.higher_items(2)
|
59
91
|
assert_equal [], li1.higher_items
|
60
92
|
end
|
61
93
|
|
94
|
+
def test_next_prev_groups_with_same_position
|
95
|
+
li1 = ListMixin.where(id: 1).first
|
96
|
+
li2 = ListMixin.where(id: 2).first
|
97
|
+
li3 = ListMixin.where(id: 3).first
|
98
|
+
li4 = ListMixin.where(id: 4).first
|
99
|
+
|
100
|
+
li3.update_column(:pos, 2) # Make the same position as li2
|
101
|
+
|
102
|
+
assert_equal [1, 2, 2, 4], ListMixin.order(:pos).pluck(:pos)
|
103
|
+
|
104
|
+
assert_equal [li3, li4], li2.lower_items
|
105
|
+
assert_equal [li2, li4], li3.lower_items
|
106
|
+
|
107
|
+
assert_equal [li3, li1], li2.higher_items
|
108
|
+
assert_equal [li2, li1], li3.higher_items
|
109
|
+
end
|
110
|
+
|
62
111
|
def test_injection
|
63
112
|
item = ListMixin.new("parent_id"=>1)
|
64
113
|
assert_equal({ parent_id: 1 }, item.scope_condition)
|
@@ -75,6 +124,9 @@ module Shared
|
|
75
124
|
new = ListMixinSub1.create("parent_id" => 20)
|
76
125
|
assert_equal 3, new.pos
|
77
126
|
|
127
|
+
new_noup = ListMixinSub1.acts_as_list_no_update { ListMixinSub1.create("parent_id" => 20) }
|
128
|
+
assert_equal_or_nil $default_position, new_noup.pos
|
129
|
+
|
78
130
|
new4 = ListMixin.create("parent_id" => 20)
|
79
131
|
assert_equal 4, new4.pos
|
80
132
|
|
@@ -98,6 +150,9 @@ module Shared
|
|
98
150
|
|
99
151
|
new4.reload
|
100
152
|
assert_equal 5, new4.pos
|
153
|
+
|
154
|
+
new_noup.reload
|
155
|
+
assert_equal_or_nil $default_position, new_noup.pos
|
101
156
|
end
|
102
157
|
|
103
158
|
def test_delete_middle
|
@@ -117,6 +172,12 @@ module Shared
|
|
117
172
|
|
118
173
|
assert_equal 1, ListMixin.where(id: 3).first.pos
|
119
174
|
assert_equal 2, ListMixin.where(id: 4).first.pos
|
175
|
+
|
176
|
+
ListMixin.acts_as_list_no_update { ListMixin.where(id: 3).first.destroy }
|
177
|
+
|
178
|
+
assert_equal [4], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
|
179
|
+
|
180
|
+
assert_equal 2, ListMixin.where(id: 4).first.pos
|
120
181
|
end
|
121
182
|
|
122
183
|
def test_acts_as_list_class
|
data/test/shared_no_addition.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Shared
|
2
4
|
module NoAddition
|
3
5
|
def setup
|
@@ -6,11 +8,11 @@ module Shared
|
|
6
8
|
|
7
9
|
def test_insert
|
8
10
|
new = NoAdditionMixin.create(parent_id: 20)
|
9
|
-
|
11
|
+
assert_nil new.pos
|
10
12
|
assert !new.in_list?
|
11
13
|
|
12
14
|
new = NoAdditionMixin.create(parent_id: 20)
|
13
|
-
|
15
|
+
assert_nil new.pos
|
14
16
|
end
|
15
17
|
|
16
18
|
def test_update_does_not_add_to_list
|
@@ -21,5 +23,51 @@ module Shared
|
|
21
23
|
assert !new.in_list?
|
22
24
|
end
|
23
25
|
|
26
|
+
def test_update_scope_does_not_add_to_list
|
27
|
+
new = NoAdditionMixin.create
|
28
|
+
|
29
|
+
new.update_attribute(:parent_id, 20)
|
30
|
+
new.reload
|
31
|
+
assert !new.in_list?
|
32
|
+
|
33
|
+
new.update_attribute(:parent_id, 5)
|
34
|
+
new.reload
|
35
|
+
assert !new.in_list?
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_collision_avoidance_with_explicit_position
|
39
|
+
first = NoAdditionMixin.create(parent_id: 20, pos: 1)
|
40
|
+
second = NoAdditionMixin.create(parent_id: 20, pos: 1)
|
41
|
+
third = NoAdditionMixin.create(parent_id: 30, pos: 1)
|
42
|
+
|
43
|
+
first.reload
|
44
|
+
second.reload
|
45
|
+
third.reload
|
46
|
+
|
47
|
+
assert_equal 2, first.pos
|
48
|
+
assert_equal 1, second.pos
|
49
|
+
assert_equal 1, third.pos
|
50
|
+
|
51
|
+
first.update(pos: 1)
|
52
|
+
|
53
|
+
first.reload
|
54
|
+
second.reload
|
55
|
+
|
56
|
+
assert_equal 1, first.pos
|
57
|
+
assert_equal 2, second.pos
|
58
|
+
|
59
|
+
first.update(parent_id: 30)
|
60
|
+
|
61
|
+
first.reload
|
62
|
+
second.reload
|
63
|
+
third.reload
|
64
|
+
|
65
|
+
assert_equal 1, first.pos
|
66
|
+
assert_equal 30, first.parent_id
|
67
|
+
assert_equal 1, second.pos
|
68
|
+
assert_equal 20, second.parent_id
|
69
|
+
assert_equal 2, third.pos
|
70
|
+
assert_equal 30, third.parent_id
|
71
|
+
end
|
24
72
|
end
|
25
73
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shared
|
4
|
+
module Quoting
|
5
|
+
|
6
|
+
def setup
|
7
|
+
3.times { |counter| QuotedList.create! order: counter }
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_create
|
11
|
+
assert_equal QuotedList.in_list.size, 3
|
12
|
+
end
|
13
|
+
|
14
|
+
# This test execute raw queries involving table name
|
15
|
+
def test_moving
|
16
|
+
item = QuotedList.first
|
17
|
+
item.higher_items
|
18
|
+
item.lower_items
|
19
|
+
item.send :bottom_item # Part of private api
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
data/test/shared_top_addition.rb
CHANGED
@@ -1,26 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Shared
|
2
4
|
module TopAddition
|
3
5
|
def setup
|
4
6
|
(1..4).each { |counter| TopAdditionMixin.create! pos: counter, parent_id: 5 }
|
5
7
|
end
|
6
8
|
|
7
|
-
def
|
8
|
-
|
9
|
+
def test_setup_state
|
10
|
+
# If we explicitly define a position (as above) then that position is what gets applied
|
11
|
+
assert_equal [1, 2, 3, 4], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
|
12
|
+
end
|
9
13
|
|
14
|
+
def test_reordering
|
10
15
|
TopAdditionMixin.where(id: 2).first.move_lower
|
11
|
-
assert_equal [
|
16
|
+
assert_equal [1, 3, 2, 4], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
|
12
17
|
|
13
18
|
TopAdditionMixin.where(id: 2).first.move_higher
|
14
|
-
assert_equal [
|
19
|
+
assert_equal [1, 2, 3, 4], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
|
15
20
|
|
16
21
|
TopAdditionMixin.where(id: 1).first.move_to_bottom
|
17
|
-
assert_equal [
|
22
|
+
assert_equal [2, 3, 4, 1], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
|
18
23
|
|
19
24
|
TopAdditionMixin.where(id: 1).first.move_to_top
|
20
|
-
assert_equal [1,
|
25
|
+
assert_equal [1, 2, 3, 4], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
|
21
26
|
|
22
27
|
TopAdditionMixin.where(id: 2).first.move_to_bottom
|
23
|
-
assert_equal [1,
|
28
|
+
assert_equal [1, 3, 4, 2], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
|
24
29
|
|
25
30
|
TopAdditionMixin.where(id: 4).first.move_to_top
|
26
31
|
assert_equal [4, 1, 3, 2], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
|
@@ -43,9 +48,14 @@ module Shared
|
|
43
48
|
assert new.first?
|
44
49
|
assert !new.last?
|
45
50
|
|
51
|
+
new = TopAdditionMixin.acts_as_list_no_update { TopAdditionMixin.create(parent_id: 20) }
|
52
|
+
assert_equal_or_nil $default_position, new.pos
|
53
|
+
assert_equal $default_position.is_a?(Integer), new.first?
|
54
|
+
assert !new.last?
|
55
|
+
|
46
56
|
new = TopAdditionMixin.create(parent_id: 20)
|
47
57
|
assert_equal 1, new.pos
|
48
|
-
|
58
|
+
assert_equal $default_position.nil?, new.first?
|
49
59
|
assert !new.last?
|
50
60
|
|
51
61
|
new = TopAdditionMixin.create(parent_id: 0)
|
@@ -64,6 +74,9 @@ module Shared
|
|
64
74
|
new = TopAdditionMixin.create(parent_id: 20)
|
65
75
|
assert_equal 1, new.pos
|
66
76
|
|
77
|
+
new = TopAdditionMixin.acts_as_list_no_update { TopAdditionMixin.create(parent_id: 20) }
|
78
|
+
assert_equal_or_nil $default_position, new.pos
|
79
|
+
|
67
80
|
new4 = TopAdditionMixin.create(parent_id: 20)
|
68
81
|
assert_equal 1, new4.pos
|
69
82
|
|
@@ -71,16 +84,26 @@ module Shared
|
|
71
84
|
assert_equal 3, new4.pos
|
72
85
|
end
|
73
86
|
|
74
|
-
def
|
75
|
-
|
87
|
+
def test_supplied_position
|
88
|
+
new = TopAdditionMixin.create(parent_id: 20, pos: 3)
|
89
|
+
assert_equal 3, new.pos
|
90
|
+
end
|
76
91
|
|
92
|
+
def test_delete_middle
|
77
93
|
TopAdditionMixin.where(id: 2).first.destroy
|
78
94
|
|
79
|
-
assert_equal [
|
95
|
+
assert_equal [1, 3, 4], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
|
80
96
|
|
81
|
-
assert_equal
|
97
|
+
assert_equal 1, TopAdditionMixin.where(id: 1).first.pos
|
82
98
|
assert_equal 2, TopAdditionMixin.where(id: 3).first.pos
|
83
|
-
assert_equal
|
99
|
+
assert_equal 3, TopAdditionMixin.where(id: 4).first.pos
|
100
|
+
|
101
|
+
TopAdditionMixin.acts_as_list_no_update { TopAdditionMixin.where(id: 3).first.destroy }
|
102
|
+
|
103
|
+
assert_equal [1, 4], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
|
104
|
+
|
105
|
+
assert_equal 1, TopAdditionMixin.where(id: 1).first.pos
|
106
|
+
assert_equal 3, TopAdditionMixin.where(id: 4).first.pos
|
84
107
|
end
|
85
108
|
|
86
109
|
end
|
data/test/shared_zero_based.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Shared
|
2
4
|
module ZeroBased
|
3
5
|
def setup
|
@@ -15,6 +17,11 @@ module Shared
|
|
15
17
|
assert !new.first?
|
16
18
|
assert new.last?
|
17
19
|
|
20
|
+
new = ZeroBasedMixin.acts_as_list_no_update { ZeroBasedMixin.create(parent_id: 20) }
|
21
|
+
assert_equal_or_nil $default_position, new.pos
|
22
|
+
assert !new.first?
|
23
|
+
assert !new.last?
|
24
|
+
|
18
25
|
new = ZeroBasedMixin.create(parent_id: 20)
|
19
26
|
assert_equal 2, new.pos
|
20
27
|
assert !new.first?
|
@@ -63,6 +70,9 @@ module Shared
|
|
63
70
|
new = ZeroBasedMixin.create(parent_id: 20)
|
64
71
|
assert_equal 2, new.pos
|
65
72
|
|
73
|
+
new_noup = ZeroBasedMixin.acts_as_list_no_update { ZeroBasedMixin.create(parent_id: 20) }
|
74
|
+
assert_equal_or_nil $default_position, new_noup.pos
|
75
|
+
|
66
76
|
new4 = ZeroBasedMixin.create(parent_id: 20)
|
67
77
|
assert_equal 3, new4.pos
|
68
78
|
|
@@ -86,6 +96,9 @@ module Shared
|
|
86
96
|
|
87
97
|
new4.reload
|
88
98
|
assert_equal 4, new4.pos
|
99
|
+
|
100
|
+
new_noup.reload
|
101
|
+
assert_equal_or_nil $default_position, new_noup.pos
|
89
102
|
end
|
90
103
|
end
|
91
104
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class Animal < ActiveRecord::Base
|
4
|
+
acts_as_list
|
5
|
+
default_scope -> { select(:name) }
|
6
|
+
end
|
7
|
+
|
8
|
+
class DefaultScopeWithSelectTest < Minitest::Test
|
9
|
+
def setup
|
10
|
+
ActiveRecord::Base.connection.create_table :animals do |t|
|
11
|
+
t.column :position, :integer
|
12
|
+
t.column :name, :string
|
13
|
+
end
|
14
|
+
|
15
|
+
ActiveRecord::Base.connection.schema_cache.clear!
|
16
|
+
Animal.reset_column_information
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def teardown
|
21
|
+
teardown_db
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_default_scope_with_select
|
26
|
+
animal1 = Animal.create name: 'Fox'
|
27
|
+
animal2 = Animal.create name: 'Panda'
|
28
|
+
animal3 = Animal.create name: 'Wildebeast'
|
29
|
+
assert_equal 1, animal1.position
|
30
|
+
assert_equal 2, animal2.position
|
31
|
+
assert_equal 3, animal3.position
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'helper'
|
4
|
+
|
5
|
+
class Section < ActiveRecord::Base
|
6
|
+
has_many :items
|
7
|
+
acts_as_list
|
8
|
+
|
9
|
+
scope :visible, -> { where(visible: true) }
|
10
|
+
end
|
11
|
+
|
12
|
+
class Item < ActiveRecord::Base
|
13
|
+
belongs_to :section
|
14
|
+
acts_as_list scope: :section
|
15
|
+
|
16
|
+
scope :visible, -> { where(visible: true).joins(:section).merge(Section.visible) }
|
17
|
+
end
|
18
|
+
|
19
|
+
class JoinedTestCase < Minitest::Test
|
20
|
+
def setup
|
21
|
+
ActiveRecord::Base.connection.create_table :sections do |t|
|
22
|
+
t.column :position, :integer
|
23
|
+
t.column :visible, :boolean, default: true
|
24
|
+
end
|
25
|
+
|
26
|
+
ActiveRecord::Base.connection.create_table :items do |t|
|
27
|
+
t.column :position, :integer
|
28
|
+
t.column :section_id, :integer
|
29
|
+
t.column :visible, :boolean, default: true
|
30
|
+
end
|
31
|
+
|
32
|
+
ActiveRecord::Base.connection.schema_cache.clear!
|
33
|
+
[Section, Item].each(&:reset_column_information)
|
34
|
+
super
|
35
|
+
end
|
36
|
+
|
37
|
+
def teardown
|
38
|
+
teardown_db
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# joining the relation returned by `#higher_items` or `#lower_items` to another table
|
44
|
+
# previously could result in ambiguous column names in the query
|
45
|
+
class TestHigherLowerItems < JoinedTestCase
|
46
|
+
def test_higher_items
|
47
|
+
section = Section.create
|
48
|
+
item1 = Item.create section: section
|
49
|
+
item2 = Item.create section: section
|
50
|
+
item3 = Item.create section: section
|
51
|
+
assert_equal item3.higher_items.visible, [item2, item1]
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_lower_items
|
55
|
+
section = Section.create
|
56
|
+
item1 = Item.create section: section
|
57
|
+
item2 = Item.create section: section
|
58
|
+
item3 = Item.create section: section
|
59
|
+
assert_equal item1.lower_items.visible, [item2, item3]
|
60
|
+
end
|
61
|
+
end
|