In ActiveRecord model after_save callback I need to ROLLBACK transaction and return false.
def after_save_callback
if mycondition?
raise ActiveRecord::Rollback
end
end
This callback rolls-back transaction but mymodel.save! returns true. How to make it return false and rollback?
If you want to abort a save in an after_save
callback, you should
raise ActiveRecord::RecordInvalid.new(self)
rather than
raise ActiveRecord::Rollback
This will not only roll back the transaction (callbacks always happen inside a possibly-implicit transaction as part of the save
or create
) but also cause save
to return false
.
Here is an article with more details: http://tech.taskrabbit.com/blog/2013/05/23/rollback-after-save/
def around_save
ActiveRecord::Base.transaction do
raise ActiveRecord::Rollback # this will actually ROLLBACK
yield # calls the actual save method
raise ActiveRecord::Rollback # this will cause a COMMIT!!! because it affect only this internal transaction.
# OTHER ACTIONS NOT EXECUTED BUT BEING A INTERNAL TRANSACTION, THE PARENT WILL COMMIT, because parent hasn't failed.
end
end
So... I think around_save come already on a transaction block, so you don't need to add that extra ActiveRecord::Base.transaction do block because rollbacks doesnt propagate up
So if you want to rollback before or after yield, you need to remove that internal transaction.
def around_save
#ActiveRecord::Base.transaction do
raise ActiveRecord::Rollback # this will actually ROLLBACK
yield # calls the actual save method
raise ActiveRecord::Rollback # this will actually ROLLBACK
# end
end
EDIT: Reading what I wrote... now seem difficult to understand. The point is: if you are gonna use aroud_save
don't wrapp again with ActiveRecord::Base.transaction
(do like in the last example) because rails will wrap the call to around_save
with is own ActiveRecord::Base.transaction
so when you raise ActiveRecord::Rollback
you are only rolling back the most internal transaction, so you can end with extrange results and partial saves (like in the first example whic is FAIL).
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