1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

multiple actions for :on option with after_commit and after_rollback

Closes #988.
This commit is contained in:
Yves Senn 2013-02-21 14:54:17 +01:00
parent b0fa9b59c8
commit d98763a602
3 changed files with 60 additions and 14 deletions

View file

@ -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.

View file

@ -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

View file

@ -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