acts_as_list 1.0.4 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/ci.yml +123 -0
- data/Appraisals +5 -1
- data/CHANGELOG.md +6 -0
- data/README.md +8 -5
- data/gemfiles/rails_6_1.gemfile +1 -1
- data/gemfiles/rails_7_0.gemfile +31 -0
- data/lib/acts_as_list/active_record/acts/callback_definer.rb +2 -4
- data/lib/acts_as_list/active_record/acts/list.rb +19 -28
- data/lib/acts_as_list/version.rb +1 -1
- data/test/database.yml +3 -1
- data/test/shared_no_addition.rb +35 -0
- data/test/test_list.rb +36 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ece77b4a7a9c6c50d1d7a188c91c6dedd4c1dba4c8ece714c2922b339c3b5490
|
4
|
+
data.tar.gz: e7d925c76332e504d6a3db3706c4362b962d5bef2f9c882023bef99a0763e2d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8ca617673d046ef18baab0a51d4e481ac10e7b044c569a9efb201c894be702aec66eb72cbc5364bb85b6374c144990fcc3c367b01cc62e0f431d87b6e41e0f4f
|
7
|
+
data.tar.gz: c1ce411f1aa503b28a837b714db52a4bcb42ae78542183f6641aa0d0f483c9c98b3521a4557554e9de539b12effeee6f901632636d61408e423c55d67287f47b
|
@@ -0,0 +1,123 @@
|
|
1
|
+
---
|
2
|
+
name: CI
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
tests:
|
7
|
+
name: Ruby ${{ matrix.ruby }}, ${{ matrix.gemfile }}, DB ${{ matrix.db }}
|
8
|
+
runs-on: ${{ matrix.os }}
|
9
|
+
strategy:
|
10
|
+
fail-fast: false
|
11
|
+
matrix:
|
12
|
+
ruby:
|
13
|
+
- 2.4
|
14
|
+
- 2.5
|
15
|
+
- 2.6
|
16
|
+
- 2.7
|
17
|
+
- '3.0'
|
18
|
+
- 3.1
|
19
|
+
- 3.2
|
20
|
+
gemfile:
|
21
|
+
- gemfiles/rails_4_2.gemfile
|
22
|
+
- gemfiles/rails_5_0.gemfile
|
23
|
+
- gemfiles/rails_5_1.gemfile
|
24
|
+
- gemfiles/rails_5_2.gemfile
|
25
|
+
- gemfiles/rails_6_0.gemfile
|
26
|
+
- gemfiles/rails_6_1.gemfile
|
27
|
+
- gemfiles/rails_7_0.gemfile
|
28
|
+
db:
|
29
|
+
- sqlite
|
30
|
+
- mysql
|
31
|
+
- postgresql
|
32
|
+
exclude:
|
33
|
+
- ruby: 2.4
|
34
|
+
gemfile: gemfiles/rails_6_0.gemfile
|
35
|
+
- ruby: 2.4
|
36
|
+
gemfile: gemfiles/rails_6_1.gemfile
|
37
|
+
- ruby: 2.4
|
38
|
+
gemfile: gemfiles/rails_7_0.gemfile
|
39
|
+
- ruby: 2.5
|
40
|
+
gemfile: gemfiles/rails_7_0.gemfile
|
41
|
+
- ruby: 2.6
|
42
|
+
gemfile: gemfiles/rails_7_0.gemfile
|
43
|
+
- ruby: 2.7
|
44
|
+
gemfile: gemfiles/rails_4_2.gemfile
|
45
|
+
- ruby: 2.7
|
46
|
+
gemfile: gemfiles/rails_5_0.gemfile
|
47
|
+
db: sqlite
|
48
|
+
- ruby: '3.0'
|
49
|
+
gemfile: gemfiles/rails_4_2.gemfile
|
50
|
+
- ruby: '3.0'
|
51
|
+
gemfile: gemfiles/rails_5_0.gemfile
|
52
|
+
- ruby: '3.0'
|
53
|
+
gemfile: gemfiles/rails_5_1.gemfile
|
54
|
+
- ruby: '3.0'
|
55
|
+
gemfile: gemfiles/rails_5_2.gemfile
|
56
|
+
- ruby: 3.1
|
57
|
+
gemfile: gemfiles/rails_4_2.gemfile
|
58
|
+
- ruby: 3.1
|
59
|
+
gemfile: gemfiles/rails_5_0.gemfile
|
60
|
+
- ruby: 3.1
|
61
|
+
gemfile: gemfiles/rails_5_1.gemfile
|
62
|
+
- ruby: 3.1
|
63
|
+
gemfile: gemfiles/rails_5_2.gemfile
|
64
|
+
- ruby: 3.1
|
65
|
+
gemfile: gemfiles/rails_6_0.gemfile
|
66
|
+
- ruby: 3.2
|
67
|
+
gemfile: gemfiles/rails_4_2.gemfile
|
68
|
+
- ruby: 3.2
|
69
|
+
gemfile: gemfiles/rails_5_0.gemfile
|
70
|
+
- ruby: 3.2
|
71
|
+
gemfile: gemfiles/rails_5_1.gemfile
|
72
|
+
- ruby: 3.2
|
73
|
+
gemfile: gemfiles/rails_5_2.gemfile
|
74
|
+
- ruby: 3.2
|
75
|
+
gemfile: gemfiles/rails_6_0.gemfile
|
76
|
+
- ruby: 3.2
|
77
|
+
gemfile: gemfiles/rails_6_1.gemfile
|
78
|
+
os:
|
79
|
+
- ubuntu-latest
|
80
|
+
services:
|
81
|
+
mysql:
|
82
|
+
image: mysql:5.7
|
83
|
+
env:
|
84
|
+
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
85
|
+
ports:
|
86
|
+
- 3306:3306
|
87
|
+
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
|
88
|
+
|
89
|
+
postgres:
|
90
|
+
# Docker Hub image
|
91
|
+
image: postgres
|
92
|
+
# Provide the password for postgres
|
93
|
+
env:
|
94
|
+
POSTGRES_USER: postgres
|
95
|
+
POSTGRES_HOST_AUTH_METHOD: trust
|
96
|
+
ports:
|
97
|
+
- 5432:5432
|
98
|
+
# Set health checks to wait until postgres has started
|
99
|
+
options: >-
|
100
|
+
--health-cmd pg_isready
|
101
|
+
--health-interval 10s
|
102
|
+
--health-timeout 5s
|
103
|
+
--health-retries 5
|
104
|
+
env:
|
105
|
+
BUNDLE_GEMFILE: ${{ matrix.gemfile }}
|
106
|
+
DB: ${{ matrix.db }}
|
107
|
+
steps:
|
108
|
+
- uses: actions/checkout@v3
|
109
|
+
- name: Set up Ruby
|
110
|
+
uses: ruby/setup-ruby@v1
|
111
|
+
with:
|
112
|
+
ruby-version: ${{ matrix.ruby }}
|
113
|
+
bundler-cache: true
|
114
|
+
- name: "Create MySQL database"
|
115
|
+
if: ${{ env.DB == 'mysql' }}
|
116
|
+
run: |
|
117
|
+
mysql -h 127.0.0.1 -u root -e 'create database acts_as_list;'
|
118
|
+
- name: "Create PostgreSQL database"
|
119
|
+
if: ${{ env.DB == 'postgresql' }}
|
120
|
+
run: |
|
121
|
+
psql -c 'create database acts_as_list;' -h localhost -U postgres
|
122
|
+
- name: Run tests
|
123
|
+
run: bundle exec rake
|
data/Appraisals
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## Unreleased
|
8
8
|
|
9
|
+
## v1.1.0 - 2023-02-01
|
10
|
+
|
11
|
+
### Fixed (Possibly Breaking)
|
12
|
+
- Use `after_save` instead of `after_commit` for `clear_scope_changed` callback [\#407](https://github.com/brendon/acts_as_list/pull/407) ([@Flixt](https://github.com/Flixt))
|
13
|
+
- Rename `add_to_list_top` and `add_to_list_bottom` private methods to `avoid_collision` that handles both cases as well as the case where `:add_new_at` is `nil`. Setting an explicit position when `:add_new_at` is `nil` will now shuffle other items out of the way if necessary. *This may break existing workarounds you have in place to deal with this bug*. [\#411](https://github.com/brendon/acts_as_list/pull/411). ([brendon])
|
14
|
+
|
9
15
|
## v1.0.4 - 2021-04-20
|
10
16
|
|
11
17
|
### Fixed
|
data/README.md
CHANGED
@@ -133,26 +133,29 @@ The `position` column is set after validations are called, so you should not put
|
|
133
133
|
If you need a scope by a non-association field you should pass an array, containing field name, to a scope:
|
134
134
|
```ruby
|
135
135
|
class TodoItem < ActiveRecord::Base
|
136
|
-
# `
|
137
|
-
acts_as_list scope: [:
|
136
|
+
# `task_category` is a plain text field (e.g. 'work', 'shopping', 'meeting'), not an association
|
137
|
+
acts_as_list scope: [:task_category]
|
138
138
|
end
|
139
139
|
```
|
140
140
|
|
141
141
|
You can also add multiple scopes in this fashion:
|
142
142
|
```ruby
|
143
143
|
class TodoItem < ActiveRecord::Base
|
144
|
-
|
144
|
+
belongs_to :todo_list
|
145
|
+
acts_as_list scope: [:task_category, :todo_list_id]
|
145
146
|
end
|
146
147
|
```
|
147
148
|
|
148
149
|
Furthermore, you can optionally include a hash of fixed parameters that will be included in all queries:
|
149
150
|
```ruby
|
150
151
|
class TodoItem < ActiveRecord::Base
|
151
|
-
|
152
|
+
belongs_to :todo_list
|
153
|
+
# or `discarded_at` if using discard
|
154
|
+
acts_as_list scope: [:task_category, :todo_list_id, deleted_at: nil]
|
152
155
|
end
|
153
156
|
```
|
154
157
|
|
155
|
-
This is useful when using this gem in conjunction with the popular [acts_as_paranoid](https://github.com/ActsAsParanoid/acts_as_paranoid)
|
158
|
+
This is useful when using this gem in conjunction with the popular [acts_as_paranoid](https://github.com/ActsAsParanoid/acts_as_paranoid) or [discard](https://github.com/jhawthorn/discard) gems.
|
156
159
|
|
157
160
|
## More Options
|
158
161
|
- `column`
|
data/gemfiles/rails_6_1.gemfile
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
|
5
|
+
gem "rake"
|
6
|
+
gem "appraisal"
|
7
|
+
gem "activerecord", "~> 7.0.0"
|
8
|
+
|
9
|
+
group :development do
|
10
|
+
gem "github_changelog_generator", "~> 1.16.0"
|
11
|
+
end
|
12
|
+
|
13
|
+
group :test do
|
14
|
+
gem "minitest", "~> 5.0"
|
15
|
+
gem "timecop"
|
16
|
+
gem "mocha"
|
17
|
+
end
|
18
|
+
|
19
|
+
group :sqlite do
|
20
|
+
gem "sqlite3", "~> 1.4"
|
21
|
+
end
|
22
|
+
|
23
|
+
group :postgresql do
|
24
|
+
gem "pg", "~> 1.3.0"
|
25
|
+
end
|
26
|
+
|
27
|
+
group :mysql do
|
28
|
+
gem "mysql2", "~> 0.5.0"
|
29
|
+
end
|
30
|
+
|
31
|
+
gemspec path: "../"
|
@@ -11,11 +11,9 @@ module ActiveRecord::Acts::List::CallbackDefiner #:nodoc:
|
|
11
11
|
before_update :check_scope, unless: :act_as_list_no_update?
|
12
12
|
after_update :update_positions, unless: :act_as_list_no_update?
|
13
13
|
|
14
|
-
|
14
|
+
after_save :clear_scope_changed
|
15
15
|
|
16
|
-
|
17
|
-
before_create "add_to_list_#{add_new_at}".to_sym, unless: :act_as_list_no_update?
|
18
|
-
end
|
16
|
+
before_create :avoid_collision, unless: :act_as_list_no_update?
|
19
17
|
end
|
20
18
|
end
|
21
19
|
end
|
@@ -229,36 +229,27 @@ module ActiveRecord
|
|
229
229
|
acts_as_list_class.default_scoped.unscope(:select, :where).where(scope_condition)
|
230
230
|
end
|
231
231
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
true
|
248
|
-
end
|
249
|
-
|
250
|
-
def add_to_list_bottom
|
251
|
-
if assume_default_position?
|
252
|
-
self[position_column] = bottom_position_in_list.to_i + 1
|
232
|
+
def avoid_collision
|
233
|
+
case add_new_at
|
234
|
+
when :top
|
235
|
+
if assume_default_position?
|
236
|
+
increment_positions_on_all_items
|
237
|
+
self[position_column] = acts_as_list_top
|
238
|
+
else
|
239
|
+
increment_positions_on_lower_items(self[position_column], id)
|
240
|
+
end
|
241
|
+
when :bottom
|
242
|
+
if assume_default_position?
|
243
|
+
self[position_column] = bottom_position_in_list.to_i + 1
|
244
|
+
else
|
245
|
+
increment_positions_on_lower_items(self[position_column], id)
|
246
|
+
end
|
253
247
|
else
|
254
|
-
increment_positions_on_lower_items(self[position_column], id)
|
248
|
+
increment_positions_on_lower_items(self[position_column], id) if position_changed
|
255
249
|
end
|
256
250
|
|
257
|
-
# Make sure we know that we've processed this scope change already
|
258
|
-
|
259
|
-
|
260
|
-
# Don't halt the callback chain
|
261
|
-
true
|
251
|
+
@scope_changed = false # Make sure we know that we've processed this scope change already
|
252
|
+
return true # Don't halt the callback chain
|
262
253
|
end
|
263
254
|
|
264
255
|
def assume_default_position?
|
@@ -454,7 +445,7 @@ module ActiveRecord
|
|
454
445
|
send('decrement_positions_on_lower_items') if lower_item
|
455
446
|
cached_changes.each { |attribute, values| send("#{attribute}=", values[1]) }
|
456
447
|
|
457
|
-
|
448
|
+
avoid_collision
|
458
449
|
end
|
459
450
|
end
|
460
451
|
|
data/lib/acts_as_list/version.rb
CHANGED
data/test/database.yml
CHANGED
@@ -4,13 +4,15 @@ sqlite:
|
|
4
4
|
|
5
5
|
mysql:
|
6
6
|
adapter: mysql2
|
7
|
+
host: 127.0.0.1
|
7
8
|
username: root
|
8
9
|
password:
|
9
10
|
database: acts_as_list
|
10
11
|
|
11
12
|
postgresql:
|
12
13
|
adapter: postgresql
|
14
|
+
host: localhost
|
13
15
|
username: postgres
|
14
|
-
password:
|
16
|
+
password: postgres
|
15
17
|
database: acts_as_list
|
16
18
|
min_messages: ERROR
|
data/test/shared_no_addition.rb
CHANGED
@@ -34,5 +34,40 @@ module Shared
|
|
34
34
|
new.reload
|
35
35
|
assert !new.in_list?
|
36
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
|
37
72
|
end
|
38
73
|
end
|
data/test/test_list.rb
CHANGED
@@ -604,6 +604,42 @@ class MultiDestroyTest < ActsAsListTestCase
|
|
604
604
|
end
|
605
605
|
end
|
606
606
|
|
607
|
+
class MultiUpdateTest < ActsAsListTestCase
|
608
|
+
|
609
|
+
def setup
|
610
|
+
setup_db
|
611
|
+
end
|
612
|
+
|
613
|
+
def test_multiple_updates_within_transaction
|
614
|
+
@page = ListMixin.create! id: 100, parent_id: nil, pos: 1
|
615
|
+
@row = ListMixin.create! parent_id: @page.id, pos: 1
|
616
|
+
@column1 = ListMixin.create! parent_id: @row.id, pos: 1
|
617
|
+
@column2 = ListMixin.create! parent_id: @row.id, pos: 2
|
618
|
+
@rich_text1 = ListMixin.create! parent_id: @column1.id, pos: 1
|
619
|
+
@rich_text2 = ListMixin.create! parent_id: @column2.id, pos: 1
|
620
|
+
|
621
|
+
ActiveRecord::Base.transaction do
|
622
|
+
@rich_text1.update!(parent_id: @column2.id, pos: 1)
|
623
|
+
|
624
|
+
assert_equal [@rich_text1.id, @rich_text2.id], ListMixin.where(parent_id: @column2.id).order('pos').map(&:id)
|
625
|
+
assert_equal [1, 2], ListMixin.where(parent_id: @column2.id).order('pos').map(&:pos)
|
626
|
+
|
627
|
+
@column1.destroy!
|
628
|
+
assert_equal [@column2.id], ListMixin.where(parent_id: @row.id).order('pos').map(&:id)
|
629
|
+
assert_equal [1], ListMixin.where(parent_id: @row.id).order('pos').map(&:pos)
|
630
|
+
|
631
|
+
@rich_text1.update!(parent_id: @page.id, pos: 1)
|
632
|
+
@rich_text2.update!(parent_id: @page.id, pos: 2)
|
633
|
+
@row.destroy!
|
634
|
+
@column2.destroy!
|
635
|
+
end
|
636
|
+
|
637
|
+
assert_equal(1, @page.reload.pos)
|
638
|
+
assert_equal [@rich_text1.id, @rich_text2.id], ListMixin.where(parent_id: @page.id).order('pos').map(&:id)
|
639
|
+
assert_equal [1, 2], ListMixin.where(parent_id: @page.id).order('pos').map(&:pos)
|
640
|
+
end
|
641
|
+
end
|
642
|
+
|
607
643
|
#class TopAdditionMixin < Mixin
|
608
644
|
|
609
645
|
class TopAdditionTest < ActsAsListTestCase
|
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: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Swanand Pagnis
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2023-01-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -51,6 +51,8 @@ extra_rdoc_files: []
|
|
51
51
|
files:
|
52
52
|
- ".gemtest"
|
53
53
|
- ".github/FUNDING.yml"
|
54
|
+
- ".github/dependabot.yml"
|
55
|
+
- ".github/workflows/ci.yml"
|
54
56
|
- ".gitignore"
|
55
57
|
- ".travis.yml"
|
56
58
|
- Appraisals
|
@@ -66,6 +68,7 @@ files:
|
|
66
68
|
- gemfiles/rails_5_2.gemfile
|
67
69
|
- gemfiles/rails_6_0.gemfile
|
68
70
|
- gemfiles/rails_6_1.gemfile
|
71
|
+
- gemfiles/rails_7_0.gemfile
|
69
72
|
- init.rb
|
70
73
|
- lib/acts_as_list.rb
|
71
74
|
- lib/acts_as_list/active_record/acts/active_record.rb
|
@@ -118,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
121
|
- !ruby/object:Gem::Version
|
119
122
|
version: '0'
|
120
123
|
requirements: []
|
121
|
-
rubygems_version: 3.0.3
|
124
|
+
rubygems_version: 3.0.3.1
|
122
125
|
signing_key:
|
123
126
|
specification_version: 4
|
124
127
|
summary: A gem adding sorting, reordering capabilities to an active_record model,
|