class TransactionCallbacksTest

Public Instance Methods

setup() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 87
def setup
  @first = TopicWithCallbacks.find(1)
end
test_after_commit_callback_should_not_swallow_errors() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 296
def test_after_commit_callback_should_not_swallow_errors
  @first.after_commit_block { fail "boom" }
  assert_raises(RuntimeError) do
    Topic.transaction do
      @first.save!
    end
  end
end
test_after_commit_callback_when_raise_should_not_restore_state() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 305
def test_after_commit_callback_when_raise_should_not_restore_state
  first = TopicWithCallbacks.new
  second = TopicWithCallbacks.new
  first.after_commit_block { fail "boom" }
  second.after_commit_block { fail "boom" }

  begin
    Topic.transaction do
      first.save!
      assert_not_nil first.id
      second.save!
      assert_not_nil second.id
    end
  rescue
  end
  assert_not_nil first.id
  assert_not_nil second.id
  assert first.reload
end
test_after_commit_callbacks_should_validate_on_condition() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 364
def test_after_commit_callbacks_should_validate_on_condition
  assert_raise(ArgumentError) { Topic.after_commit(on: :save) }
  e = assert_raise(ArgumentError) { Topic.after_commit(on: "create") }
  assert_match(/:on conditions for after_commit and after_rollback callbacks have to be one of \[:create, :destroy, :update\]/, e.message)
end
test_after_rollback_callback_should_not_swallow_errors_when_set_to_raise() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 325
def test_after_rollback_callback_should_not_swallow_errors_when_set_to_raise
  error_class = Class.new(StandardError)
  @first.after_rollback_block { raise error_class }
  assert_raises(error_class) do
    Topic.transaction do
      @first.save!
      raise ActiveRecord::Rollback
    end
  end
end
test_after_rollback_callback_when_raise_should_restore_state() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 336
def test_after_rollback_callback_when_raise_should_restore_state
  error_class = Class.new(StandardError)

  first = TopicWithCallbacks.new
  second = TopicWithCallbacks.new
  first.after_rollback_block { raise error_class }
  second.after_rollback_block { raise error_class }

  begin
    Topic.transaction do
      first.save!
      assert_not_nil first.id
      second.save!
      assert_not_nil second.id
      raise ActiveRecord::Rollback
    end
  rescue error_class
  end
  assert_nil first.id
  assert_nil second.id
end
test_after_rollback_callbacks_should_validate_on_condition() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 358
def test_after_rollback_callbacks_should_validate_on_condition
  assert_raise(ArgumentError) { Topic.after_rollback(on: :save) }
  e = assert_raise(ArgumentError) { Topic.after_rollback(on: "create") }
  assert_match(/:on conditions for after_commit and after_rollback callbacks have to be one of \[:create, :destroy, :update\]/, e.message)
end
test_before_commit_exception_should_pop_transaction_stack() click to toggle source

FIXME: Test behavior, not implementation.

# File activerecord/test/cases/transaction_callbacks_test.rb, line 92
def test_before_commit_exception_should_pop_transaction_stack
  @first.before_commit_block { raise "better pop this txn from the stack!" }

  original_txn = @first.class.connection.current_transaction

  begin
    @first.save!
    fail
  rescue
    assert_equal original_txn, @first.class.connection.current_transaction
  end
end
test_call_after_commit_after_transaction_commits() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 105
def test_call_after_commit_after_transaction_commits
  @first.after_commit_block { |r| r.history << :after_commit }
  @first.after_rollback_block { |r| r.history << :after_rollback }

  @first.save!
  assert_equal [:after_commit], @first.history
end
test_call_after_rollback_after_transaction_rollsback() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 172
def test_call_after_rollback_after_transaction_rollsback
  @first.after_commit_block { |r| r.history << :after_commit }
  @first.after_rollback_block { |r| r.history << :after_rollback }

  Topic.transaction do
    @first.save!
    raise ActiveRecord::Rollback
  end

  assert_equal [:after_rollback], @first.history
end
test_call_after_rollback_when_commit_fails() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 229
def test_call_after_rollback_when_commit_fails
  @first.after_commit_block { |r| r.history << :after_commit }
  @first.after_rollback_block { |r| r.history << :after_rollback }

  assert_raises RuntimeError do
    @first.transaction do
      tx = @first.class.connection.transaction_manager.current_transaction
      def tx.commit
        raise
      end

      @first.save
    end
  end

  assert_equal [:after_rollback], @first.history
end
test_only_call_after_commit_on_create_after_transaction_commits_for_new_record() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 127
def test_only_call_after_commit_on_create_after_transaction_commits_for_new_record
  new_record = TopicWithCallbacks.new(title: "New topic", written_on: Date.today)
  add_transaction_execution_blocks new_record

  new_record.save!
  assert_equal [:commit_on_create], new_record.history
end
test_only_call_after_commit_on_create_after_transaction_commits_for_new_record_if_create_succeeds_creating_through_association() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 135
def test_only_call_after_commit_on_create_after_transaction_commits_for_new_record_if_create_succeeds_creating_through_association
  topic = TopicWithCallbacks.create!(title: "New topic", written_on: Date.today)
  reply = topic.replies.create

  assert_equal [], reply.history
end
test_only_call_after_commit_on_create_and_doesnt_leaky() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 142
def test_only_call_after_commit_on_create_and_doesnt_leaky
  r = ReplyWithCallbacks.new(content: "foo")
  r.save_on_after_create = true
  r.save!
  r.content = "bar"
  r.save!
  r.save!
  assert_equal [:commit_on_create], r.history
end
test_only_call_after_commit_on_destroy_after_transaction_commits_for_destroyed_record() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 120
def test_only_call_after_commit_on_destroy_after_transaction_commits_for_destroyed_record
  add_transaction_execution_blocks @first

  @first.destroy
  assert_equal [:commit_on_destroy], @first.history
end
test_only_call_after_commit_on_top_level_transactions() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 159
def test_only_call_after_commit_on_top_level_transactions
  @first.after_commit_block { |r| r.history << :after_commit }
  assert @first.history.empty?

  @first.transaction do
    @first.transaction(requires_new: true) do
      @first.touch
    end
    assert @first.history.empty?
  end
  assert_equal [:after_commit], @first.history
end
test_only_call_after_commit_on_update_after_transaction_commits_for_existing_record() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 113
def test_only_call_after_commit_on_update_after_transaction_commits_for_existing_record
  add_transaction_execution_blocks @first

  @first.save!
  assert_equal [:commit_on_update], @first.history
end
test_only_call_after_commit_on_update_after_transaction_commits_for_existing_record_on_touch() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 152
def test_only_call_after_commit_on_update_after_transaction_commits_for_existing_record_on_touch
  add_transaction_execution_blocks @first

  @first.touch
  assert_equal [:commit_on_update], @first.history
end
test_only_call_after_rollback_on_create_after_transaction_rollsback_for_new_record() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 217
def test_only_call_after_rollback_on_create_after_transaction_rollsback_for_new_record
  new_record = TopicWithCallbacks.new(title: "New topic", written_on: Date.today)
  add_transaction_execution_blocks new_record

  Topic.transaction do
    new_record.save!
    raise ActiveRecord::Rollback
  end

  assert_equal [:rollback_on_create], new_record.history
end
test_only_call_after_rollback_on_destroy_after_transaction_rollsback_for_destroyed_record() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 206
def test_only_call_after_rollback_on_destroy_after_transaction_rollsback_for_destroyed_record
  add_transaction_execution_blocks @first

  Topic.transaction do
    @first.destroy
    raise ActiveRecord::Rollback
  end

  assert_equal [:rollback_on_destroy], @first.history
end
test_only_call_after_rollback_on_records_rolled_back_to_a_savepoint() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 247
def test_only_call_after_rollback_on_records_rolled_back_to_a_savepoint
  def @first.rollbacks(i = 0); @rollbacks ||= 0; @rollbacks += i if i; end
  def @first.commits(i = 0); @commits ||= 0; @commits += i if i; end
  @first.after_rollback_block { |r| r.rollbacks(1) }
  @first.after_commit_block { |r| r.commits(1) }

  second = TopicWithCallbacks.find(3)
  def second.rollbacks(i = 0); @rollbacks ||= 0; @rollbacks += i if i; end
  def second.commits(i = 0); @commits ||= 0; @commits += i if i; end
  second.after_rollback_block { |r| r.rollbacks(1) }
  second.after_commit_block { |r| r.commits(1) }

  Topic.transaction do
    @first.save!
    Topic.transaction(requires_new: true) do
      second.save!
      raise ActiveRecord::Rollback
    end
  end

  assert_equal 1, @first.commits
  assert_equal 0, @first.rollbacks
  assert_equal 0, second.commits
  assert_equal 1, second.rollbacks
end
test_only_call_after_rollback_on_records_rolled_back_to_a_savepoint_when_release_savepoint_fails() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 273
def test_only_call_after_rollback_on_records_rolled_back_to_a_savepoint_when_release_savepoint_fails
  def @first.rollbacks(i = 0); @rollbacks ||= 0; @rollbacks += i if i; end
  def @first.commits(i = 0); @commits ||= 0; @commits += i if i; end

  @first.after_rollback_block { |r| r.rollbacks(1) }
  @first.after_commit_block { |r| r.commits(1) }

  Topic.transaction do
    @first.save
    Topic.transaction(requires_new: true) do
      @first.save!
      raise ActiveRecord::Rollback
    end
    Topic.transaction(requires_new: true) do
      @first.save!
      raise ActiveRecord::Rollback
    end
  end

  assert_equal 1, @first.commits
  assert_equal 2, @first.rollbacks
end
test_only_call_after_rollback_on_update_after_transaction_rollsback_for_existing_record() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 184
def test_only_call_after_rollback_on_update_after_transaction_rollsback_for_existing_record
  add_transaction_execution_blocks @first

  Topic.transaction do
    @first.save!
    raise ActiveRecord::Rollback
  end

  assert_equal [:rollback_on_update], @first.history
end
test_only_call_after_rollback_on_update_after_transaction_rollsback_for_existing_record_on_touch() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 195
def test_only_call_after_rollback_on_update_after_transaction_rollsback_for_existing_record_on_touch
  add_transaction_execution_blocks @first

  Topic.transaction do
    @first.touch
    raise ActiveRecord::Rollback
  end

  assert_equal [:rollback_on_update], @first.history
end
test_saving_a_record_with_a_belongs_to_that_specifies_touching_the_parent_should_call_callbacks_on_the_parent_object() click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 370
def test_saving_a_record_with_a_belongs_to_that_specifies_touching_the_parent_should_call_callbacks_on_the_parent_object
  pet   = Pet.first
  owner = pet.owner
  flag = false

  owner.on_after_commit do
    flag = true
  end

  pet.name = "Fluffy the Third"
  pet.save

  assert flag
end

Private Instance Methods

add_transaction_execution_blocks(record) click to toggle source
# File activerecord/test/cases/transaction_callbacks_test.rb, line 387
def add_transaction_execution_blocks(record)
  record.after_commit_block(:create) { |r| r.history << :commit_on_create }
  record.after_commit_block(:update) { |r| r.history << :commit_on_update }
  record.after_commit_block(:destroy) { |r| r.history << :commit_on_destroy }
  record.after_rollback_block(:create) { |r| r.history << :rollback_on_create }
  record.after_rollback_block(:update) { |r| r.history << :rollback_on_update }
  record.after_rollback_block(:destroy) { |r| r.history << :rollback_on_destroy }
end