Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

after_commit callbacks run in the wrong order #46983

Closed
ghiculescu opened this issue Jan 12, 2023 · 1 comment
Closed

after_commit callbacks run in the wrong order #46983

ghiculescu opened this issue Jan 12, 2023 · 1 comment

Comments

@ghiculescu
Copy link
Member

ghiculescu commented Jan 12, 2023

Steps to reproduce

# frozen_string_literal: true

require "bundler/inline"

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

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  gem "rails", github: "rails/rails", branch: "main"
  gem "sqlite3"
end

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

ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :posts
end

class Post < ActiveRecord::Base
  before_create :before_create_one
  before_create :before_create_two

  after_create :after_create_one
  after_create :after_create_two

  after_commit :after_commit_one, on: :create
  after_commit :after_commit_two, on: :create

  before_commit :before_commit_one, on: :create
  before_commit :before_commit_two, on: :create

  def before_create_one
    puts "before_create_one"
  end
  def before_create_two
    puts "before_create_two"
  end

  def after_create_one
    puts "after_create_one"
  end
  def after_create_two
    puts "after_create_two"
  end

  def after_commit_one
    puts "after_commit_one"
  end
  def after_commit_two
    puts "after_commit_two"
  end

  def before_commit_one
    puts "before_commit_one"
  end
  def before_commit_two
    puts "before_commit_two"
  end
end

class BugTest < Minitest::Test
  def test_association_stuff
    Post.create!
  end
end

Expected behavior

For every callback type, the _one callback should run before the _two callback.

Actual behavior

before_create_one
before_create_two
D, [2023-01-12T15:15:28.727473 #68445] DEBUG -- :   TRANSACTION (0.0ms)  begin transaction
D, [2023-01-12T15:15:28.727589 #68445] DEBUG -- :   Post Create (0.2ms)  INSERT INTO "posts" DEFAULT VALUES
after_create_one
after_create_two
before_commit_one
before_commit_two
D, [2023-01-12T15:15:28.727811 #68445] DEBUG -- :   TRANSACTION (0.0ms)  commit transaction
after_commit_two
after_commit_one

Every type is correct except after_commit.

As a workaround, I can do this, to get the callbacks to run in the order I want (but not in the order the code suggests):

  after_commit :after_commit_one, on: :create
  after_commit :after_commit_two, on: :create, prepend: true

System configuration

Rails version: main

Ruby version: 3.1.3

@rafaelfranca
Copy link
Member

This is by design. Duplicated of #20911

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants