New Upstream Release - ruby-acts-as-list
Ready changes
Summary
Merged new upstream version: 1.1.0 (was: 1.0.4).
Resulting package
Built on 2023-02-24T23:40 (took 2m13s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-releases ruby-acts-as-list
Lintian Result
Diff
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..5ace460
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,6 @@
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..c905b07
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,123 @@
+---
+name: CI
+on: [push, pull_request]
+
+jobs:
+ tests:
+ name: Ruby ${{ matrix.ruby }}, ${{ matrix.gemfile }}, DB ${{ matrix.db }}
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ ruby:
+ - 2.4
+ - 2.5
+ - 2.6
+ - 2.7
+ - '3.0'
+ - 3.1
+ - 3.2
+ gemfile:
+ - gemfiles/rails_4_2.gemfile
+ - gemfiles/rails_5_0.gemfile
+ - gemfiles/rails_5_1.gemfile
+ - gemfiles/rails_5_2.gemfile
+ - gemfiles/rails_6_0.gemfile
+ - gemfiles/rails_6_1.gemfile
+ - gemfiles/rails_7_0.gemfile
+ db:
+ - sqlite
+ - mysql
+ - postgresql
+ exclude:
+ - ruby: 2.4
+ gemfile: gemfiles/rails_6_0.gemfile
+ - ruby: 2.4
+ gemfile: gemfiles/rails_6_1.gemfile
+ - ruby: 2.4
+ gemfile: gemfiles/rails_7_0.gemfile
+ - ruby: 2.5
+ gemfile: gemfiles/rails_7_0.gemfile
+ - ruby: 2.6
+ gemfile: gemfiles/rails_7_0.gemfile
+ - ruby: 2.7
+ gemfile: gemfiles/rails_4_2.gemfile
+ - ruby: 2.7
+ gemfile: gemfiles/rails_5_0.gemfile
+ db: sqlite
+ - ruby: '3.0'
+ gemfile: gemfiles/rails_4_2.gemfile
+ - ruby: '3.0'
+ gemfile: gemfiles/rails_5_0.gemfile
+ - ruby: '3.0'
+ gemfile: gemfiles/rails_5_1.gemfile
+ - ruby: '3.0'
+ gemfile: gemfiles/rails_5_2.gemfile
+ - ruby: 3.1
+ gemfile: gemfiles/rails_4_2.gemfile
+ - ruby: 3.1
+ gemfile: gemfiles/rails_5_0.gemfile
+ - ruby: 3.1
+ gemfile: gemfiles/rails_5_1.gemfile
+ - ruby: 3.1
+ gemfile: gemfiles/rails_5_2.gemfile
+ - ruby: 3.1
+ gemfile: gemfiles/rails_6_0.gemfile
+ - ruby: 3.2
+ gemfile: gemfiles/rails_4_2.gemfile
+ - ruby: 3.2
+ gemfile: gemfiles/rails_5_0.gemfile
+ - ruby: 3.2
+ gemfile: gemfiles/rails_5_1.gemfile
+ - ruby: 3.2
+ gemfile: gemfiles/rails_5_2.gemfile
+ - ruby: 3.2
+ gemfile: gemfiles/rails_6_0.gemfile
+ - ruby: 3.2
+ gemfile: gemfiles/rails_6_1.gemfile
+ os:
+ - ubuntu-latest
+ services:
+ mysql:
+ image: mysql:5.7
+ env:
+ MYSQL_ALLOW_EMPTY_PASSWORD: yes
+ ports:
+ - 3306:3306
+ options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
+
+ postgres:
+ # Docker Hub image
+ image: postgres
+ # Provide the password for postgres
+ env:
+ POSTGRES_USER: postgres
+ POSTGRES_HOST_AUTH_METHOD: trust
+ ports:
+ - 5432:5432
+ # Set health checks to wait until postgres has started
+ options: >-
+ --health-cmd pg_isready
+ --health-interval 10s
+ --health-timeout 5s
+ --health-retries 5
+ env:
+ BUNDLE_GEMFILE: ${{ matrix.gemfile }}
+ DB: ${{ matrix.db }}
+ steps:
+ - uses: actions/checkout@v3
+ - name: Set up Ruby
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: ${{ matrix.ruby }}
+ bundler-cache: true
+ - name: "Create MySQL database"
+ if: ${{ env.DB == 'mysql' }}
+ run: |
+ mysql -h 127.0.0.1 -u root -e 'create database acts_as_list;'
+ - name: "Create PostgreSQL database"
+ if: ${{ env.DB == 'postgresql' }}
+ run: |
+ psql -c 'create database acts_as_list;' -h localhost -U postgres
+ - name: Run tests
+ run: bundle exec rake
diff --git a/Appraisals b/Appraisals
index e94ebef..4b48737 100644
--- a/Appraisals
+++ b/Appraisals
@@ -36,5 +36,9 @@ appraise "rails-6-0" do
end
appraise "rails-6-1" do
- gem "activerecord", "6.1.0.rc1"
+ gem "activerecord", "~> 6.1.0"
+end
+
+appraise "rails-7-0" do
+ gem "activerecord", "~> 7.0.0"
end
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 271741a..9ebf741 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
+## v1.1.0 - 2023-02-01
+
+### Fixed (Possibly Breaking)
+- 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))
+- 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])
+
## v1.0.4 - 2021-04-20
### Fixed
diff --git a/README.md b/README.md
index 651ab59..44a1192 100644
--- a/README.md
+++ b/README.md
@@ -133,26 +133,29 @@ The `position` column is set after validations are called, so you should not put
If you need a scope by a non-association field you should pass an array, containing field name, to a scope:
```ruby
class TodoItem < ActiveRecord::Base
- # `kind` is a plain text field (e.g. 'work', 'shopping', 'meeting'), not an association
- acts_as_list scope: [:kind]
+ # `task_category` is a plain text field (e.g. 'work', 'shopping', 'meeting'), not an association
+ acts_as_list scope: [:task_category]
end
```
You can also add multiple scopes in this fashion:
```ruby
class TodoItem < ActiveRecord::Base
- acts_as_list scope: [:kind, :owner_id]
+ belongs_to :todo_list
+ acts_as_list scope: [:task_category, :todo_list_id]
end
```
Furthermore, you can optionally include a hash of fixed parameters that will be included in all queries:
```ruby
class TodoItem < ActiveRecord::Base
- acts_as_list scope: [:kind, :owner_id, deleted_at: nil]
+ belongs_to :todo_list
+ # or `discarded_at` if using discard
+ acts_as_list scope: [:task_category, :todo_list_id, deleted_at: nil]
end
```
-This is useful when using this gem in conjunction with the popular [acts_as_paranoid](https://github.com/ActsAsParanoid/acts_as_paranoid) gem.
+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.
## More Options
- `column`
diff --git a/debian/changelog b/debian/changelog
index 0e3b5c5..2b9e874 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+ruby-acts-as-list (1.1.0-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk> Fri, 24 Feb 2023 23:38:44 -0000
+
ruby-acts-as-list (1.0.4-1) unstable; urgency=medium
[ Andrius Merkys ]
diff --git a/debian/patches/0001-Remove-bundler-setup-from-tests.patch b/debian/patches/0001-Remove-bundler-setup-from-tests.patch
index 77a1e36..574ec12 100644
--- a/debian/patches/0001-Remove-bundler-setup-from-tests.patch
+++ b/debian/patches/0001-Remove-bundler-setup-from-tests.patch
@@ -6,10 +6,10 @@ Subject: Remove bundler setup from tests
test/helper.rb | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
-diff --git a/test/helper.rb b/test/helper.rb
-index 0a23919..f0f8faa 100644
---- a/test/helper.rb
-+++ b/test/helper.rb
+Index: ruby-acts-as-list.git/test/helper.rb
+===================================================================
+--- ruby-acts-as-list.git.orig/test/helper.rb
++++ ruby-acts-as-list.git/test/helper.rb
@@ -2,19 +2,10 @@
# $DEBUG = true
diff --git a/gemfiles/rails_6_1.gemfile b/gemfiles/rails_7_0.gemfile
similarity index 77%
rename from gemfiles/rails_6_1.gemfile
rename to gemfiles/rails_7_0.gemfile
index 9b2f40d..03bf15e 100644
--- a/gemfiles/rails_6_1.gemfile
+++ b/gemfiles/rails_7_0.gemfile
@@ -4,10 +4,10 @@ source "http://rubygems.org"
gem "rake"
gem "appraisal"
-gem "activerecord", "6.1.0.rc1"
+gem "activerecord", "~> 7.0.0"
group :development do
- gem "github_changelog_generator", "1.9.0"
+ gem "github_changelog_generator", "~> 1.16.0"
end
group :test do
@@ -21,7 +21,7 @@ group :sqlite do
end
group :postgresql do
- gem "pg", "~> 1.2.0"
+ gem "pg", "~> 1.3.0"
end
group :mysql do
diff --git a/lib/acts_as_list/active_record/acts/callback_definer.rb b/lib/acts_as_list/active_record/acts/callback_definer.rb
index 5e7e53a..9769e49 100644
--- a/lib/acts_as_list/active_record/acts/callback_definer.rb
+++ b/lib/acts_as_list/active_record/acts/callback_definer.rb
@@ -11,11 +11,9 @@ module ActiveRecord::Acts::List::CallbackDefiner #:nodoc:
before_update :check_scope, unless: :act_as_list_no_update?
after_update :update_positions, unless: :act_as_list_no_update?
- after_commit :clear_scope_changed
+ after_save :clear_scope_changed
- if add_new_at.present?
- before_create "add_to_list_#{add_new_at}".to_sym, unless: :act_as_list_no_update?
- end
+ before_create :avoid_collision, unless: :act_as_list_no_update?
end
end
end
diff --git a/lib/acts_as_list/active_record/acts/list.rb b/lib/acts_as_list/active_record/acts/list.rb
index 90294ac..094fb55 100644
--- a/lib/acts_as_list/active_record/acts/list.rb
+++ b/lib/acts_as_list/active_record/acts/list.rb
@@ -229,36 +229,27 @@ module ActiveRecord
acts_as_list_class.default_scoped.unscope(:select, :where).where(scope_condition)
end
- # Poorly named methods. They will insert the item at the desired position if the position
- # has been set manually using position=, not necessarily the top or bottom of the list:
-
- def add_to_list_top
- if assume_default_position?
- increment_positions_on_all_items
- self[position_column] = acts_as_list_top
- else
- increment_positions_on_lower_items(self[position_column], id)
- end
-
- # Make sure we know that we've processed this scope change already
- @scope_changed = false
-
- # Don't halt the callback chain
- true
- end
-
- def add_to_list_bottom
- if assume_default_position?
- self[position_column] = bottom_position_in_list.to_i + 1
+ def avoid_collision
+ case add_new_at
+ when :top
+ if assume_default_position?
+ increment_positions_on_all_items
+ self[position_column] = acts_as_list_top
+ else
+ increment_positions_on_lower_items(self[position_column], id)
+ end
+ when :bottom
+ if assume_default_position?
+ self[position_column] = bottom_position_in_list.to_i + 1
+ else
+ increment_positions_on_lower_items(self[position_column], id)
+ end
else
- increment_positions_on_lower_items(self[position_column], id)
+ increment_positions_on_lower_items(self[position_column], id) if position_changed
end
- # Make sure we know that we've processed this scope change already
- @scope_changed = false
-
- # Don't halt the callback chain
- true
+ @scope_changed = false # Make sure we know that we've processed this scope change already
+ return true # Don't halt the callback chain
end
def assume_default_position?
@@ -454,7 +445,7 @@ module ActiveRecord
send('decrement_positions_on_lower_items') if lower_item
cached_changes.each { |attribute, values| send("#{attribute}=", values[1]) }
- send("add_to_list_#{add_new_at}") if add_new_at.present?
+ avoid_collision
end
end
diff --git a/lib/acts_as_list/version.rb b/lib/acts_as_list/version.rb
index d055bcb..bae8f36 100644
--- a/lib/acts_as_list/version.rb
+++ b/lib/acts_as_list/version.rb
@@ -3,7 +3,7 @@
module ActiveRecord
module Acts
module List
- VERSION = '1.0.4'
+ VERSION = '1.1.0'
end
end
end
diff --git a/test/database.yml b/test/database.yml
index 8c4cfe5..b15954f 100644
--- a/test/database.yml
+++ b/test/database.yml
@@ -4,13 +4,15 @@ sqlite:
mysql:
adapter: mysql2
+ host: 127.0.0.1
username: root
password:
database: acts_as_list
postgresql:
adapter: postgresql
+ host: localhost
username: postgres
- password:
+ password: postgres
database: acts_as_list
min_messages: ERROR
diff --git a/test/shared_no_addition.rb b/test/shared_no_addition.rb
index 4d9b294..f80c4db 100644
--- a/test/shared_no_addition.rb
+++ b/test/shared_no_addition.rb
@@ -34,5 +34,40 @@ module Shared
new.reload
assert !new.in_list?
end
+
+ def test_collision_avoidance_with_explicit_position
+ first = NoAdditionMixin.create(parent_id: 20, pos: 1)
+ second = NoAdditionMixin.create(parent_id: 20, pos: 1)
+ third = NoAdditionMixin.create(parent_id: 30, pos: 1)
+
+ first.reload
+ second.reload
+ third.reload
+
+ assert_equal 2, first.pos
+ assert_equal 1, second.pos
+ assert_equal 1, third.pos
+
+ first.update(pos: 1)
+
+ first.reload
+ second.reload
+
+ assert_equal 1, first.pos
+ assert_equal 2, second.pos
+
+ first.update(parent_id: 30)
+
+ first.reload
+ second.reload
+ third.reload
+
+ assert_equal 1, first.pos
+ assert_equal 30, first.parent_id
+ assert_equal 1, second.pos
+ assert_equal 20, second.parent_id
+ assert_equal 2, third.pos
+ assert_equal 30, third.parent_id
+ end
end
end
diff --git a/test/test_list.rb b/test/test_list.rb
index 8a3d313..11148f3 100644
--- a/test/test_list.rb
+++ b/test/test_list.rb
@@ -604,6 +604,42 @@ class MultiDestroyTest < ActsAsListTestCase
end
end
+class MultiUpdateTest < ActsAsListTestCase
+
+ def setup
+ setup_db
+ end
+
+ def test_multiple_updates_within_transaction
+ @page = ListMixin.create! id: 100, parent_id: nil, pos: 1
+ @row = ListMixin.create! parent_id: @page.id, pos: 1
+ @column1 = ListMixin.create! parent_id: @row.id, pos: 1
+ @column2 = ListMixin.create! parent_id: @row.id, pos: 2
+ @rich_text1 = ListMixin.create! parent_id: @column1.id, pos: 1
+ @rich_text2 = ListMixin.create! parent_id: @column2.id, pos: 1
+
+ ActiveRecord::Base.transaction do
+ @rich_text1.update!(parent_id: @column2.id, pos: 1)
+
+ assert_equal [@rich_text1.id, @rich_text2.id], ListMixin.where(parent_id: @column2.id).order('pos').map(&:id)
+ assert_equal [1, 2], ListMixin.where(parent_id: @column2.id).order('pos').map(&:pos)
+
+ @column1.destroy!
+ assert_equal [@column2.id], ListMixin.where(parent_id: @row.id).order('pos').map(&:id)
+ assert_equal [1], ListMixin.where(parent_id: @row.id).order('pos').map(&:pos)
+
+ @rich_text1.update!(parent_id: @page.id, pos: 1)
+ @rich_text2.update!(parent_id: @page.id, pos: 2)
+ @row.destroy!
+ @column2.destroy!
+ end
+
+ assert_equal(1, @page.reload.pos)
+ assert_equal [@rich_text1.id, @rich_text2.id], ListMixin.where(parent_id: @page.id).order('pos').map(&:id)
+ assert_equal [1, 2], ListMixin.where(parent_id: @page.id).order('pos').map(&:pos)
+ end
+end
+
#class TopAdditionMixin < Mixin
class TopAdditionTest < ActsAsListTestCase
Debdiff
[The following lists of changes regard files as different if they have different names, permissions or owners.]
Files in second set of .debs but not in first
-rw-r--r-- root/root /usr/share/rubygems-integration/all/specifications/acts_as_list-1.1.0.gemspec
Files in first set of .debs but not in second
-rw-r--r-- root/root /usr/share/rubygems-integration/all/specifications/acts_as_list-1.0.4.gemspec
No differences were encountered in the control files