acts_as_list 0.7.7 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +10 -5
- data/gemfiles/rails_4_1.gemfile +0 -6
- data/lib/acts_as_list/active_record/acts/list.rb +37 -20
- data/lib/acts_as_list/version.rb +1 -1
- data/test/shared_list_sub.rb +28 -2
- data/test/shared_top_addition.rb +18 -12
- data/test/test_joined_list.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf7464bb2c953b31ccf95b2e3017ce77cf9e40bc
|
4
|
+
data.tar.gz: f65a617c773c1c5ebad2b85827fc675da6c23d2c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 664518e270eafe5380772fe9dab0d661ab6184b526648ba1322f28d4c04040e9d412f00b011abe072eb289d73dc422be0aa411b1e759d2933c5ea05d08ef8773
|
7
|
+
data.tar.gz: ffd987ff9646c697fe2972ff2516bcc66286d528c71af311e8fe27524568d5eaad6ee774cd351345a2c8aaad8326fd9c42bd83dd9acf77d3f34dfb2a98d99d2d
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [v0.7.7](https://github.com/swanandp/acts_as_list/tree/v0.7.7) (2016-08-18)
|
4
|
+
[Full Changelog](https://github.com/swanandp/acts_as_list/compare/v0.7.6...v0.7.7)
|
5
|
+
|
6
|
+
**Closed issues:**
|
7
|
+
|
8
|
+
- Issue after upgrading to 0.7.5: No connection pool with id primary found. [\#214](https://github.com/swanandp/acts_as_list/issues/214)
|
9
|
+
- Changing scope is inconsistent based on add\_new\_at [\#138](https://github.com/swanandp/acts_as_list/issues/138)
|
10
|
+
- Duplicate positions and lost items [\#76](https://github.com/swanandp/acts_as_list/issues/76)
|
11
|
+
|
12
|
+
**Merged pull requests:**
|
13
|
+
|
14
|
+
- Add quoted table names to some columns [\#221](https://github.com/swanandp/acts_as_list/pull/221) ([jpalumickas](https://github.com/jpalumickas))
|
15
|
+
- Appraisals cleanup [\#217](https://github.com/swanandp/acts_as_list/pull/217) ([brendon](https://github.com/brendon))
|
16
|
+
- Fix insert\_at\_position in race condition [\#195](https://github.com/swanandp/acts_as_list/pull/195) ([danielross](https://github.com/danielross))
|
17
|
+
|
3
18
|
## [v0.7.6](https://github.com/swanandp/acts_as_list/tree/v0.7.6) (2016-07-15)
|
4
19
|
[Full Changelog](https://github.com/swanandp/acts_as_list/compare/v0.7.5...v0.7.6)
|
5
20
|
|
data/README.md
CHANGED
@@ -4,6 +4,13 @@
|
|
4
4
|
|
5
5
|
This `acts_as` extension provides the capabilities for sorting and reordering a number of objects in a list. The class that has this specified needs to have a `position` column defined as an integer on the mapped database table.
|
6
6
|
|
7
|
+
## 0.8.0 Upgrade Notes
|
8
|
+
|
9
|
+
There are a couple of changes of behaviour from `0.8.0` onwards:
|
10
|
+
|
11
|
+
- If you specify `add_new_at: :top`, new items will be added to the top of the list like always. But now, if you specify a position at insert time: `.create(position: 3)`, the position will be respected. In this example, the item will end up at position `3` and will move other items further down the list. Before `0.8.0` the position would be ignored and the item would still be added to the top of the list. [#220](https://github.com/swanandp/acts_as_list/pull/220)
|
12
|
+
- `acts_as_list` now copes with disparate position integers (i.e. gaps between the numbers). There has been a change in behaviour for the `higher_items` method. It now returns items with the first item in the collection being the closest item to the reference item, and the last item in the collection being the furthest from the reference item (a.k.a. the first item in the list). [#223](https://github.com/swanandp/acts_as_list/pull/223)
|
13
|
+
|
7
14
|
## Installation
|
8
15
|
|
9
16
|
In your Gemfile:
|
@@ -71,8 +78,6 @@ In `acts_as_list`, "higher" means further up the list (a lower `position`), and
|
|
71
78
|
- `list_item.lower_items` will return all the items below `list_item` in the list (ordered by the position, ascending)
|
72
79
|
|
73
80
|
## Notes
|
74
|
-
If the `position` column has a default value, then there is a slight change in behavior, i.e if you have 4 items in the list, and you insert 1, with a default position 0, it would be pushed to the bottom of the list. Please look at the tests for this and some recent pull requests for discussions related to this.
|
75
|
-
|
76
81
|
All `position` queries (select, update, etc.) inside gem methods are executed without the default scope (i.e. `Model.unscoped`), this will prevent nasty issues when the default scope is different from `acts_as_list` scope.
|
77
82
|
|
78
83
|
The `position` column is set after validations are called, so you should not put a `presence` validation on the `position` column.
|
@@ -88,11 +93,11 @@ end
|
|
88
93
|
|
89
94
|
## More Options
|
90
95
|
- `column`
|
91
|
-
default:
|
96
|
+
default: `position`. Use this option if the column name in your database is different from position.
|
92
97
|
- `top_of_list`
|
93
|
-
default:
|
98
|
+
default: `1`. Use this option to define the top of the list. Use 0 to make the collection act more like an array in its indexing.
|
94
99
|
- `add_new_at`
|
95
|
-
default:
|
100
|
+
default: `:bottom`. Use this option to specify whether objects get added to the `:top` or `:bottom` of the list. `nil` will result in new items not being added to the list on create, i.e, position will be kept nil after create.
|
96
101
|
|
97
102
|
## Versions
|
98
103
|
As of version `0.7.5` Rails 5 is supported.
|
data/gemfiles/rails_4_1.gemfile
CHANGED
@@ -174,8 +174,12 @@ module ActiveRecord
|
|
174
174
|
return unless lower_item
|
175
175
|
|
176
176
|
acts_as_list_class.transaction do
|
177
|
-
lower_item.
|
178
|
-
|
177
|
+
if lower_item.send(position_column) != self.send(position_column)
|
178
|
+
swap_positions(lower_item, self)
|
179
|
+
else
|
180
|
+
lower_item.decrement_position
|
181
|
+
increment_position
|
182
|
+
end
|
179
183
|
end
|
180
184
|
end
|
181
185
|
|
@@ -184,8 +188,12 @@ module ActiveRecord
|
|
184
188
|
return unless higher_item
|
185
189
|
|
186
190
|
acts_as_list_class.transaction do
|
187
|
-
higher_item.
|
188
|
-
|
191
|
+
if higher_item.send(position_column) != self.send(position_column)
|
192
|
+
swap_positions(higher_item, self)
|
193
|
+
else
|
194
|
+
higher_item.increment_position
|
195
|
+
decrement_position
|
196
|
+
end
|
189
197
|
end
|
190
198
|
end
|
191
199
|
|
@@ -236,16 +244,14 @@ module ActiveRecord
|
|
236
244
|
set_list_position(self.send(position_column).to_i - 1)
|
237
245
|
end
|
238
246
|
|
239
|
-
# Return +true+ if this object is the first in the list.
|
240
247
|
def first?
|
241
248
|
return false unless in_list?
|
242
|
-
|
249
|
+
!higher_item
|
243
250
|
end
|
244
251
|
|
245
|
-
# Return +true+ if this object is the last in the list.
|
246
252
|
def last?
|
247
253
|
return false unless in_list?
|
248
|
-
|
254
|
+
!lower_item
|
249
255
|
end
|
250
256
|
|
251
257
|
# Return the next higher item in the list.
|
@@ -261,9 +267,8 @@ module ActiveRecord
|
|
261
267
|
position_value = send(position_column)
|
262
268
|
acts_as_list_list.
|
263
269
|
where("#{quoted_position_column_with_table_name} < ?", position_value).
|
264
|
-
|
265
|
-
limit(limit)
|
266
|
-
order("#{quoted_position_column_with_table_name} ASC")
|
270
|
+
order("#{quoted_position_column_with_table_name} DESC").
|
271
|
+
limit(limit)
|
267
272
|
end
|
268
273
|
|
269
274
|
# Return the next lower item in the list.
|
@@ -279,9 +284,8 @@ module ActiveRecord
|
|
279
284
|
position_value = send(position_column)
|
280
285
|
acts_as_list_list.
|
281
286
|
where("#{quoted_position_column_with_table_name} > ?", position_value).
|
282
|
-
|
283
|
-
limit(limit)
|
284
|
-
order("#{quoted_position_column_with_table_name} ASC")
|
287
|
+
order("#{quoted_position_column_with_table_name} ASC").
|
288
|
+
limit(limit)
|
285
289
|
end
|
286
290
|
|
287
291
|
# Test if this record is in a list
|
@@ -308,23 +312,36 @@ module ActiveRecord
|
|
308
312
|
end
|
309
313
|
|
310
314
|
private
|
315
|
+
|
316
|
+
def swap_positions(item1, item2)
|
317
|
+
item1.set_list_position(item2.send(position_column))
|
318
|
+
item2.set_list_position(item1.send("#{position_column}_was"))
|
319
|
+
end
|
320
|
+
|
311
321
|
def acts_as_list_list
|
312
322
|
acts_as_list_class.unscoped do
|
313
323
|
acts_as_list_class.where(scope_condition)
|
314
324
|
end
|
315
325
|
end
|
316
326
|
|
327
|
+
# Poorly named methods. They will insert the item at the desired position if the position
|
328
|
+
# has been set manually using position=, not necessarily the top or bottom of the list:
|
329
|
+
|
317
330
|
def add_to_list_top
|
318
|
-
|
319
|
-
|
331
|
+
if not_in_list? || internal_scope_changed? && !position_changed || default_position?
|
332
|
+
increment_positions_on_all_items
|
333
|
+
self[position_column] = acts_as_list_top
|
334
|
+
else
|
335
|
+
increment_positions_on_lower_items(self[position_column], id)
|
336
|
+
end
|
337
|
+
|
320
338
|
# Make sure we know that we've processed this scope change already
|
321
339
|
@scope_changed = false
|
322
|
-
|
340
|
+
|
341
|
+
# Don't halt the callback chain
|
323
342
|
true
|
324
343
|
end
|
325
344
|
|
326
|
-
# A poorly named method. It will insert the item at the desired position if the position
|
327
|
-
# has been set manually using position=, not necessarily the bottom of the list
|
328
345
|
def add_to_list_bottom
|
329
346
|
if not_in_list? || internal_scope_changed? && !position_changed || default_position?
|
330
347
|
self[position_column] = bottom_position_in_list.to_i + 1
|
@@ -335,7 +352,7 @@ module ActiveRecord
|
|
335
352
|
# Make sure we know that we've processed this scope change already
|
336
353
|
@scope_changed = false
|
337
354
|
|
338
|
-
#
|
355
|
+
# Don't halt the callback chain
|
339
356
|
true
|
340
357
|
end
|
341
358
|
|
data/lib/acts_as_list/version.rb
CHANGED
data/test/shared_list_sub.rb
CHANGED
@@ -43,6 +43,32 @@ 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
|
+
|
53
|
+
ListMixin.where(id: 2).first.move_lower
|
54
|
+
assert_equal [1, 3, 2, 4], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
|
55
|
+
|
56
|
+
ListMixin.where(id: 2).first.move_higher
|
57
|
+
assert_equal [1, 2, 3, 4], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
|
58
|
+
|
59
|
+
ListMixin.where(id: 1).first.move_to_bottom
|
60
|
+
assert_equal [2, 3, 4, 1], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
|
61
|
+
|
62
|
+
ListMixin.where(id: 1).first.move_to_top
|
63
|
+
assert_equal [1, 2, 3, 4], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
|
64
|
+
|
65
|
+
ListMixin.where(id: 2).first.move_to_bottom
|
66
|
+
assert_equal [1, 3, 4, 2], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
|
67
|
+
|
68
|
+
ListMixin.where(id: 4).first.move_to_top
|
69
|
+
assert_equal [4, 1, 3, 2], ListMixin.where(parent_id: 5000).order('pos').map(&:id)
|
70
|
+
end
|
71
|
+
|
46
72
|
def test_next_prev_groups
|
47
73
|
li1 = ListMixin.where(id: 1).first
|
48
74
|
li2 = ListMixin.where(id: 2).first
|
@@ -53,9 +79,9 @@ module Shared
|
|
53
79
|
assert_equal [li2, li3], li1.lower_items(2)
|
54
80
|
assert_equal [], li4.lower_items
|
55
81
|
|
56
|
-
assert_equal [
|
82
|
+
assert_equal [li2, li1], li3.higher_items
|
57
83
|
assert_equal [li1], li2.higher_items
|
58
|
-
assert_equal [
|
84
|
+
assert_equal [li3, li2], li4.higher_items(2)
|
59
85
|
assert_equal [], li1.higher_items
|
60
86
|
end
|
61
87
|
|
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)
|
@@ -71,16 +74,19 @@ module Shared
|
|
71
74
|
assert_equal 3, new4.pos
|
72
75
|
end
|
73
76
|
|
74
|
-
def
|
75
|
-
|
77
|
+
def test_supplied_position
|
78
|
+
new = TopAdditionMixin.create(parent_id: 20, pos: 3)
|
79
|
+
assert_equal 3, new.pos
|
80
|
+
end
|
76
81
|
|
82
|
+
def test_delete_middle
|
77
83
|
TopAdditionMixin.where(id: 2).first.destroy
|
78
84
|
|
79
|
-
assert_equal [
|
85
|
+
assert_equal [1, 3, 4], TopAdditionMixin.where(parent_id: 5).order('pos').map(&:id)
|
80
86
|
|
81
|
-
assert_equal
|
87
|
+
assert_equal 1, TopAdditionMixin.where(id: 1).first.pos
|
82
88
|
assert_equal 2, TopAdditionMixin.where(id: 3).first.pos
|
83
|
-
assert_equal
|
89
|
+
assert_equal 3, TopAdditionMixin.where(id: 4).first.pos
|
84
90
|
end
|
85
91
|
|
86
92
|
end
|
data/test/test_joined_list.rb
CHANGED
@@ -51,7 +51,7 @@ class TestHigherLowerItems < JoinedTestCase
|
|
51
51
|
item1 = Item.create section: section
|
52
52
|
item2 = Item.create section: section
|
53
53
|
item3 = Item.create section: section
|
54
|
-
assert_equal item3.higher_items.visible, [
|
54
|
+
assert_equal item3.higher_items.visible, [item2, item1]
|
55
55
|
end
|
56
56
|
|
57
57
|
def test_lower_items
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_list
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2016-08-
|
13
|
+
date: 2016-08-23 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|