Return false and rollback in after_save callback

In the ActiveRecord model, after the after_save callback, I need to complete the ROLLBACK transaction and return false.

def after_save_callback if mycondition? raise ActiveRecord::Rollback end end 

This transaction is a reverse transaction, but mymodel.save! returns true. How to return false and rollback?

+4
source share
3 answers

I don't think you can do this with after_save Instead, you should look around_save :

 def around_save ActiveRecord::Base.transaction do yield # calls the actual save method raise ActiveRecord::Rollback if my_condition? end end 
-1
source

If you want to abort saving in the after_save , you must

 raise ActiveRecord::RecordInvalid.new(self) 

but not

 raise ActiveRecord::Rollback 

This is not only a transaction rollback (callbacks always occur inside a potentially implicit transaction as part of save or create ), but also cause a save false returned.

Here is an article with more detailed information: http://tech.taskrabbit.com/blog/2013/05/23/rollback-after-save/

+5
source
 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 that around_save has already come into the transaction block, so you do not need to add this additional block ActiveRecord :: Base.transaction do, because rollbacks do not apply

So, if you want to roll back before or after the exit, you need to delete this 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 seems hard to understand. The fact is that if you are going to use aroud_save , do not complete the wrapper using ActiveRecord::Base.transaction ( do in the last example ), because the rails wrap around_save call around_save with your own ActiveRecord::Base.transaction so when you raise ActiveRecord::Rollback , you roll back only the innermost transaction, so you can end with the results of emergency processing and partial savings (for example, in the first FAIL example).

+4
source

Source: https://habr.com/ru/post/1403511/


All Articles