Skip to content

after_commit for inner transaction has different object id #39714

@SheldonNunes

Description

@SheldonNunes

I have a model that has a queue structure that should be executed on after_commit. The model is saved within a nested transaction and the queue is not executing. I have discovered that the after_commit model has a different object_id from the one in the inner transaction.

Steps to reproduce

I created a reproducible test case:
Note: I have tried with both the inclusion and exclusion of Company.transaction(requires_new: true)

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  # Activate the gem you are reporting the issue against.
  gem "activerecord", "6.0.3"
  gem "sqlite3"
end

require "active_record"
require "minitest/autorun"
require "logger"

# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :companies, force: true do |t|
    t.string :name, null: false
  end
end

$actual_after_commit_call_objects = []

class Company < ActiveRecord::Base
  after_commit { $actual_after_commit_call_objects << object_id }
end

class BugTest < ActiveSupport::TestCase
  include ActiveRecord::TestFixtures

  self.use_transactional_tests = true

  def test_commit_callbacks_for_identical_ar_model
    expected_after_commit_call_objects = []
    Company.create(name:"S")
    Company.transaction do
      Company.find(1).tap do |company| # object A
        expected_after_commit_call_objects << company.object_id
        company.name = "A"
        company.save!
      end
      Company.transaction do
        Company.find(1).tap do |company| # object A
          expected_after_commit_call_objects << company.object_id
          company.name = "B"
          company.save!
        end
      end
    end
    assert_equal expected_after_commit_call_objects, $actual_after_commit_call_objects
  end
end

Expected behavior

Expected behavior is that the object id of from the inner transaction and after_commit callback should be the same

Actual behavior

The outermost transaction has matching object id (note: they are not in the same position in the expected/actual) but the inner transaction has different object id.

--- expected
+++ actual
@@ -1 +1 @@
-[70320209145860, 70320209176540]
+[70320208918760, 70320209145860]

System configuration

Rails version: 6.0.2.1
Activerecord version: "6.0.3"
Ruby version:
ruby 2.6.3p62

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions