Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Tree: 6cbed09e11
Fetching contributors…

Cannot retrieve contributors at this time

191 lines (166 sloc) 6.801 kB
module AfterCommit
module ConnectionAdapters
def self.included(base)
base.class_eval do
def transaction_with_callback(*args, &block)
# @disable_rollback is set to false at the start of the
# outermost call to #transaction. After committing, it is
# set to true to prevent exceptions causing a spurious
# rollback.
outermost_call = @disable_rollback.nil?
@disable_rollback = false if outermost_call
transaction_without_callback(*args, &block)
ensure
@disable_rollback = nil if outermost_call
end
alias_method_chain :transaction, :callback
# The commit_db_transaction method gets called when the outermost
# transaction finishes and everything inside commits. We want to
# override it so that after this happens, any records that were saved
# or destroyed within this transaction now get their after_commit
# callback fired.
def commit_db_transaction_with_callback
increment_transaction_pointer
result = nil
begin
trigger_before_commit_callbacks
trigger_before_commit_on_create_callbacks
trigger_before_commit_on_update_callbacks
trigger_before_commit_on_save_callbacks
trigger_before_commit_on_destroy_callbacks
result = commit_db_transaction_without_callback
@disable_rollback = true
trigger_after_commit_callbacks
trigger_after_commit_on_create_callbacks
trigger_after_commit_on_update_callbacks
trigger_after_commit_on_save_callbacks
trigger_after_commit_on_destroy_callbacks
result
rescue
# Need to decrement the transaction pointer before calling
# rollback... to ensure it is not incremented twice
unless @disable_rollback
decrement_transaction_pointer
@already_decremented = true
end
# We still want to raise the exception.
raise
ensure
AfterCommit.cleanup(self)
decrement_transaction_pointer unless @already_decremented
end
end
alias_method_chain :commit_db_transaction, :callback
# In the event the transaction fails and rolls back, nothing inside
# should recieve the after_commit callback, but do fire the after_rollback
# callback for each record that failed to be committed.
def rollback_db_transaction_with_callback
return if @disable_rollback
increment_transaction_pointer
begin
result = nil
trigger_before_rollback_callbacks
result = rollback_db_transaction_without_callback
trigger_after_rollback_callbacks
result
ensure
AfterCommit.cleanup(self)
decrement_transaction_pointer
end
decrement_transaction_pointer
end
alias_method_chain :rollback_db_transaction, :callback
def unique_transaction_key
[object_id, transaction_pointer]
end
def old_transaction_key
[object_id, transaction_pointer - 1]
end
protected
def trigger_before_commit_callbacks
AfterCommit.records(self).each do |record|
record.send :callback, :before_commit
end
end
def trigger_before_commit_on_create_callbacks
AfterCommit.created_records(self).each do |record|
record.send :callback, :before_commit_on_create
end
end
def trigger_before_commit_on_update_callbacks
AfterCommit.updated_records(self).each do |record|
record.send :callback, :before_commit_on_update
end
end
def trigger_before_commit_on_save_callbacks
AfterCommit.saved_records(self).each do |record|
record.send :callback, :before_commit_on_save
end
end
def trigger_before_commit_on_destroy_callbacks
AfterCommit.destroyed_records(self).each do |record|
record.send :callback, :before_commit_on_destroy
end
end
def trigger_before_rollback_callbacks
AfterCommit.records(self).each do |record|
record.send :callback, :before_rollback
end
end
def trigger_after_commit_callbacks
# Trigger the after_commit callback for each of the committed
# records.
AfterCommit.records(self).each do |record|
record.send :callback, :after_commit
end
end
def trigger_after_commit_on_create_callbacks
# Trigger the after_commit_on_create callback for each of the committed
# records.
AfterCommit.created_records(self).each do |record|
record.send :callback, :after_commit_on_create
end
end
def trigger_after_commit_on_update_callbacks
# Trigger the after_commit_on_update callback for each of the committed
# records.
AfterCommit.updated_records(self).each do |record|
record.send :callback, :after_commit_on_update
end
end
def trigger_after_commit_on_save_callbacks
# Trigger the after_commit_on_save callback for each of the committed
# records.
AfterCommit.saved_records(self).each do |record|
record.send :callback, :after_commit_on_save
end
end
def trigger_after_commit_on_destroy_callbacks
# Trigger the after_commit_on_destroy callback for each of the committed
# records.
AfterCommit.destroyed_records(self).each do |record|
record.send :callback, :after_commit_on_destroy
end
end
def trigger_after_rollback_callbacks
# Trigger the after_rollback callback for each of the committed
# records.
AfterCommit.records(self).each do |record|
record.send :callback, :after_rollback
end
end
def transaction_pointer
Thread.current[:after_commit_pointer] ||= 0
end
def increment_transaction_pointer
Thread.current[:after_commit_pointer] ||= 0
Thread.current[:after_commit_pointer] += 1
end
def decrement_transaction_pointer
Thread.current[:after_commit_pointer] ||= 0
Thread.current[:after_commit_pointer] -= 1
end
end
end
end
end
Jump to Line
Something went wrong with that request. Please try again.