diff --git a/Appraisals b/Appraisals index bbb12469..a3e41317 100644 --- a/Appraisals +++ b/Appraisals @@ -65,7 +65,9 @@ appraise 'rails_5.2' do end appraise 'norails' do + gem 'sqlite3', '~> 1.3', '>= 1.3.5', platforms: :ruby gem 'rails', install_if: false + gem 'after_commit_action', install_if: false gem 'sequel' gem 'redis-objects' end diff --git a/Gemfile b/Gemfile index 793030f8..0208cff2 100644 --- a/Gemfile +++ b/Gemfile @@ -4,3 +4,4 @@ gemspec gem 'sqlite3', '~> 1.3.5', :platforms => :ruby gem 'rails', '5.1.4' +gem 'after_commit_action', '~> 1.0' diff --git a/README.md b/README.md index 11beb23e..d69b1724 100644 --- a/README.md +++ b/README.md @@ -981,6 +981,12 @@ job.run job.save! #notify_about_running_job is not run ``` +Please note that `:after_commit` AASM callbacks behaves around custom implementation +of transaction pattern rather than a real-life DB transaction. This fact still causes +the race conditions and redundant callback calls within nested transaction. In order +to fix that it's highly recommended to add `gem 'after_commit_action', '~> 1.0'` to your +`Gemfile`. + If you want to encapsulate state changes within an own transaction, the behavior of this nested transaction might be confusing. Take a look at [ActiveRecord Nested Transactions](http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html) diff --git a/aasm.gemspec b/aasm.gemspec index b52f2098..4aa07451 100644 --- a/aasm.gemspec +++ b/aasm.gemspec @@ -17,7 +17,6 @@ Gem::Specification.new do |s| s.required_ruby_version = '>= 1.9.3' s.add_dependency 'concurrent-ruby', '~> 1.0' - s.add_dependency 'after_commit_action', '~> 1.0' s.add_development_dependency 'rake' s.add_development_dependency 'sdoc' diff --git a/gemfiles/norails.gemfile b/gemfiles/norails.gemfile index a3329fa3..b5ec4654 100644 --- a/gemfiles/norails.gemfile +++ b/gemfiles/norails.gemfile @@ -4,6 +4,7 @@ source "https://rubygems.org" gem "sqlite3", "~> 1.3", ">= 1.3.5", platforms: :ruby gem "rails", install_if: false +gem "after_commit_action", install_if: false gem "sequel" gem "redis-objects" diff --git a/gemfiles/rails_3.2.gemfile b/gemfiles/rails_3.2.gemfile index 0a1bba64..2ca77465 100644 --- a/gemfiles/rails_3.2.gemfile +++ b/gemfiles/rails_3.2.gemfile @@ -4,6 +4,7 @@ source "https://rubygems.org" gem "sqlite3", "~> 1.3.5", platforms: :ruby gem "rails", "~> 3.2.22" +gem "after_commit_action", "~> 1.0" gem "mongoid", "~> 3.1" gem "sequel" gem "bson_ext", platforms: :ruby diff --git a/gemfiles/rails_4.2.gemfile b/gemfiles/rails_4.2.gemfile index f30ad6f8..86ffeea9 100644 --- a/gemfiles/rails_4.2.gemfile +++ b/gemfiles/rails_4.2.gemfile @@ -4,6 +4,7 @@ source "https://rubygems.org" gem "sqlite3", "~> 1.3.5", platforms: :ruby gem "rails", "4.2.5" +gem "after_commit_action", "~> 1.0" gem "nokogiri", "1.6.8.1", platforms: [:ruby_19] gem "mime-types", "~> 2", platforms: [:ruby_19, :jruby] gem "mongoid", "~> 4.0" diff --git a/gemfiles/rails_4.2_mongoid_5.gemfile b/gemfiles/rails_4.2_mongoid_5.gemfile index d267cfc3..6d499793 100644 --- a/gemfiles/rails_4.2_mongoid_5.gemfile +++ b/gemfiles/rails_4.2_mongoid_5.gemfile @@ -4,6 +4,7 @@ source "https://rubygems.org" gem "sqlite3", "~> 1.3.5", platforms: :ruby gem "rails", "4.2.5" +gem "after_commit_action", "~> 1.0" gem "mime-types", "~> 2", platforms: [:ruby_19, :jruby] gem "mongoid", "~> 5.0" gem "activerecord-jdbcsqlite3-adapter", "1.3.24", platforms: :jruby diff --git a/gemfiles/rails_4.2_nobrainer.gemfile b/gemfiles/rails_4.2_nobrainer.gemfile index fef73be4..f68ef931 100644 --- a/gemfiles/rails_4.2_nobrainer.gemfile +++ b/gemfiles/rails_4.2_nobrainer.gemfile @@ -4,6 +4,7 @@ source "https://rubygems.org" gem "sqlite3", "~> 1.3.5", platforms: :ruby gem "rails", "4.2.5" +gem "after_commit_action", "~> 1.0" gem "nobrainer", "~> 0.33.0" gemspec path: "../" diff --git a/gemfiles/rails_5.0.gemfile b/gemfiles/rails_5.0.gemfile index a9fd7ac9..9185d15c 100644 --- a/gemfiles/rails_5.0.gemfile +++ b/gemfiles/rails_5.0.gemfile @@ -4,6 +4,7 @@ source "https://rubygems.org" gem "sqlite3", "~> 1.3.5", platforms: :ruby gem "rails", "5.0.0" +gem "after_commit_action", "~> 1.0" gem "mongoid", "~> 6.0" gem "sequel" gem "dynamoid", "~> 1.3", platforms: :ruby diff --git a/gemfiles/rails_5.0_nobrainer.gemfile b/gemfiles/rails_5.0_nobrainer.gemfile index b5a237c8..fa1607f3 100644 --- a/gemfiles/rails_5.0_nobrainer.gemfile +++ b/gemfiles/rails_5.0_nobrainer.gemfile @@ -4,6 +4,7 @@ source "https://rubygems.org" gem "sqlite3", "~> 1.3.5", platforms: :ruby gem "rails", "5.0.0" +gem "after_commit_action", "~> 1.0" gem "nobrainer", "~> 0.33.0" gemspec path: "../" diff --git a/gemfiles/rails_5.1.gemfile b/gemfiles/rails_5.1.gemfile index de25b9ca..c6006f51 100644 --- a/gemfiles/rails_5.1.gemfile +++ b/gemfiles/rails_5.1.gemfile @@ -4,6 +4,7 @@ source "https://rubygems.org" gem "sqlite3", "~> 1.3.5", platforms: :ruby gem "rails", "5.1" +gem "after_commit_action", "~> 1.0" gem "mongoid", "~>6.0" gem "sequel" gem "dynamoid", "~> 1.3", platforms: :ruby diff --git a/gemfiles/rails_5.2.gemfile b/gemfiles/rails_5.2.gemfile index 87a645e1..52ff6c8a 100644 --- a/gemfiles/rails_5.2.gemfile +++ b/gemfiles/rails_5.2.gemfile @@ -4,6 +4,7 @@ source "https://rubygems.org" gem "sqlite3", "~> 1.3.5", platforms: :ruby gem "rails", "5.2" +gem "after_commit_action", "~> 1.0" gem "mongoid", "~>6.0" gem "sequel" gem "dynamoid", "~>2.2", platforms: :ruby diff --git a/lib/aasm/persistence/active_record_persistence.rb b/lib/aasm/persistence/active_record_persistence.rb index 171224b2..4f72fd2b 100644 --- a/lib/aasm/persistence/active_record_persistence.rb +++ b/lib/aasm/persistence/active_record_persistence.rb @@ -1,4 +1,3 @@ -require 'after_commit_action' require 'aasm/persistence/orm' module AASM module Persistence @@ -29,7 +28,17 @@ module ActiveRecordPersistence # end # def self.included(base) - base.send(:include, ::AfterCommitAction) unless base.include?(::AfterCommitAction) + begin + require 'after_commit_action' + base.send(:include, ::AfterCommitAction) unless base.include?(::AfterCommitAction) + base.send(:alias_method, :aasm_execute_after_commit, :execute_after_commit) + rescue LoadError + warn <<-MSG +[DEPRECATION] :after_commit AASM callback is not safe in terms of race conditions and redundant calls. + Please add `gem 'after_commit_action', '~> 1.0'` to your Gemfile in order to fix that. + MSG + end + base.send(:include, AASM::Persistence::Base) base.send(:include, AASM::Persistence::ORM) base.send(:include, AASM::Persistence::ActiveRecordPersistence::InstanceMethods) @@ -90,12 +99,6 @@ def aasm_transaction(requires_new, requires_lock) end end - def aasm_execute_after_commit - execute_after_commit do - yield - end - end - def aasm_enum(name=:default) case AASM::StateMachineStore.fetch(self.class, true).machine(name).config.enum when false then nil