aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/CHANGELOG.md8
-rw-r--r--activerecord/lib/active_record/transactions.rb31
-rw-r--r--activerecord/test/cases/transaction_callbacks_test.rb35
3 files changed, 60 insertions, 14 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 3410f38063..8e51fdf199 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,5 +1,13 @@
## Rails 4.0.0 (unreleased) ##
+* The `:on` option for `after_commit` and `after_rollback` now
+ accepts an Array of actions.
+ Fixes #988.
+
+ Example:
+
+ after_commit :update_cache on: [:create, :update]
+
* Rename related indexes on `rename_table` and `rename_column`. This
does not affect indexes with custom names.
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index 4b7a388dc7..33718ef0e9 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -218,9 +218,8 @@ module ActiveRecord
# after_commit :do_bar, on: :update
# after_commit :do_baz, on: :destroy
#
- # Also, to have the callback fired on create and update, but not on destroy:
- #
- # after_commit :do_zoo, if: :persisted?
+ # after_commit :do_foo_bar, :on [:create, :update]
+ # after_commit :do_bar_baz, :on [:update, :destroy]
#
# Note that transactional fixtures do not play well with this feature. Please
# use the +test_after_commit+ gem to have these hooks fired in tests.
@@ -244,12 +243,14 @@ module ActiveRecord
if options.is_a?(Hash) && options[:on]
assert_valid_transaction_action(options[:on])
options[:if] = Array(options[:if])
- options[:if] << "transaction_include_action?(:#{options[:on]})"
+ fire_on = Array(options[:on]).map(&:to_sym)
+ options[:if] << "transaction_include_any_action?(#{fire_on})"
end
end
- def assert_valid_transaction_action(action)
- unless ACTIONS.include?(action.to_sym)
+ def assert_valid_transaction_action(actions)
+ actions = Array(actions)
+ if (actions - ACTIONS).any?
raise ArgumentError, ":on conditions for after_commit and after_rollback callbacks have to be one of #{ACTIONS.join(",")}"
end
end
@@ -378,14 +379,16 @@ module ActiveRecord
end
# Determine if a transaction included an action for :create, :update, or :destroy. Used in filtering callbacks.
- def transaction_include_action?(action) #:nodoc:
- case action
- when :create
- transaction_record_state(:new_record)
- when :destroy
- destroyed?
- when :update
- !(transaction_record_state(:new_record) || destroyed?)
+ def transaction_include_any_action?(actions) #:nodoc:
+ actions.any? do |action|
+ case action
+ when :create
+ transaction_record_state(:new_record)
+ when :destroy
+ destroyed?
+ when :update
+ !(transaction_record_state(:new_record) || destroyed?)
+ end
end
end
end
diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb
index fd5651b4e0..eb4ffd4498 100644
--- a/activerecord/test/cases/transaction_callbacks_test.rb
+++ b/activerecord/test/cases/transaction_callbacks_test.rb
@@ -312,3 +312,38 @@ class SaveFromAfterCommitBlockTest < ActiveRecord::TestCase
assert_equal true, topic.record_updated
end
end
+
+class CallbacksOnMultipleActionsTest < ActiveRecord::TestCase
+ self.use_transactional_fixtures = false
+
+ class TopicWithCallbacksOnMultipleActions < ActiveRecord::Base
+ self.table_name = :topics
+
+ after_commit(on: [:create, :destroy]) { |record| record.history << :create_and_destroy }
+ after_commit(on: [:create, :update]) { |record| record.history << :create_and_update }
+ after_commit(on: [:update, :destroy]) { |record| record.history << :update_and_destroy }
+
+ def clear_history
+ @history = []
+ end
+
+ def history
+ @history ||= []
+ end
+ end
+
+ def test_after_commit_on_multiple_actions
+ topic = TopicWithCallbacksOnMultipleActions.new
+ topic.save
+ assert_equal [:create_and_update, :create_and_destroy], topic.history
+
+ topic.clear_history
+ topic.approved = true
+ topic.save
+ assert_equal [:update_and_destroy, :create_and_update], topic.history
+
+ topic.clear_history
+ topic.destroy
+ assert_equal [:update_and_destroy, :create_and_destroy], topic.history
+ end
+end