I have defined after_commit
callback on update
. It doesn't trigger in rspec.
Here is my callback :
after_commit :notify_trip, :if => Proc.new { |trip| trip.can_send_schedule_notification? }, on: :update
Here is my rspec code :
@work_order.update_attributes(:status_id => statuses(:scheduled).id, :tour_id => @tour.id)
@work_order.run_callbacks(:commit)
assert_equal 1, ActionMailer::Base.deliveries.size
expect(ActionMailer::Base.deliveries[0].to).to include(@user.email)
expect(ActionMailer::Base.deliveries[0].subject).to include("Your trip has been scheduled!")
Here callback is not calling and ActionMailer::Base.deliveries.size
returning 0
Is there any suggestion on this.
TL;DR
@work_order.update_attributes(:status_id => statuses(:scheduled).id, :tour_id => @tour.id)
@work_order.instance_variable_set(:@_start_transaction_state, {})
@work_order.run_callbacks(:commit)
Explanation
I had a same similar situation with Rails 4.0.1:
@work_order = WorkOrder.create(status_id: 1, order_id: 2)
@work_order.update_attributes(status_id: 4, order_id: 5)
@work_order.run_callbacks(:commit)
when the model implementation look something like this:
class WorkOrder < ActiveRecord::Base
after_commit :notify_trip, :if => Proc.new { |trip| trip.can_send_schedule_notification? }, on: :update
after_commit :do_something, on: :create
end
and every time when I call @work_order.run_callbacks(:commit)
then it would run the after_commit on create method - do_something. That happens because after the @work_order
is created by (@work_order = WorkOrder.create(status_id: 1, order_id: 2)
) a instance variable called @_start_transaction_state
is initialized, but never cleared. @_start_transaction_state
is used in ActiveRecord::Transaction module to track a transaction process as far as I understood from reading the code.
So before calling run_callbacks
if we clear up @_start_transaction_state
, then we will be able to run the after_commit on: update
callbacks
@work_order.instance_variable_set(:@_start_transaction_state, {})
@work_order.run_callbacks(:commit)
There's one more option which is a little bit cleaner:
@work_order.send(:clear_transaction_record_state)
@work_order.run_callbacks(:commit)
I know that the solution is hacky and I'm not sure if that might introduce some side effects, especially with nested transactions, but was the only variant that worked for me in Rails 4.0.1.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With