John Bachir
John Bachir

Reputation: 22711

Why does the presence of after_create_commit make my after_update_commit never fire?

I'm seeing a scenario where i have something like this:

class User
  def thing; puts "hello"; end
  after_update_commit :thing
  after_create_commit :thing
end

the after_update_commit never fires when doing user.update first_name: rand but if i comment out after_create_commit, it does work.

Is this a Rails bug or is there a reason for this?

rails 6.1.4.6

Upvotes: 3

Views: 3683

Answers (2)

metacorn
metacorn

Reputation: 52

As it was said in John Bachir answer you may have different conditions for create and for update actions (and these conditions may be complicated). I ended up with:

class User
  def thing; puts "hello"; end
  after_commit :thing_on_create, on: :create, if: :create_condition?
  after_commit :thing_on_update, on: :update, if: :update_condition?

  alias_method :thing_on_create, :thing
  alias_method :thing_on_update, :thing

  def create_condition?
    Time.now.monday?
  end

  def update_condition?
    active?
  end
end

It is a little bit more readable (and does not affect the method itself) IMO.

Upvotes: 2

John Bachir
John Bachir

Reputation: 22711

https://guides.rubyonrails.org/active_record_callbacks.html#transaction-callbacks

Using both after_create_commit and after_update_commit with the same method name will only allow the last callback defined to take effect, as they both internally alias to after_commit which overrides previously defined callbacks with the same method name.

solution if don't have conditions:

after_commit :thing, on: [:update, :create]

solution if do have condition (in this case, is_active? on update)

after_commit :thing, on: [:update, :create]

def thing
  # id_previously_changed? is only true when record is created
  unless id_previously_changed?
    return unless is_active?
  end

# ...
end

Upvotes: 9

Related Questions