Jon*_*nas 7 activerecord ruby-on-rails
在ActiveRecord模型中,after_save回调我需要ROLLBACK事务并返回false.
def after_save_callback
if mycondition?
raise ActiveRecord::Rollback
end
end
Run Code Online (Sandbox Code Playgroud)
这个回调回滚事务但mymodel.save!返回true.如何让它返回false和rollback?
Pau*_*rth 15
如果你想在after_save回调中中止保存,你应该
raise ActiveRecord::RecordInvalid.new(self)
Run Code Online (Sandbox Code Playgroud)
而不是
raise ActiveRecord::Rollback
Run Code Online (Sandbox Code Playgroud)
这不仅会回滚事务(回调总是发生在可能隐式事务中作为saveor的一部分create),而且还会导致save返回false.
这是一篇更详细的文章: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
Run Code Online (Sandbox Code Playgroud)
所以...我认为around_save已经出现在一个事务块上,所以你不需要添加额外的ActiveRecord :: Base.transaction do block,因为回滚不会传播
因此,如果要在yield之前或之后回滚,则需要删除该内部事务.
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
Run Code Online (Sandbox Code Playgroud)
编辑:阅读我写的内容......现在看起来很难理解.关键是:如果你要aroud_save再次使用不再使用ActiveRecord::Base.transaction(在上一个例子中做)因为rails会将调用包装around_save为自己,ActiveRecord::Base.transaction所以当你raise ActiveRecord::Rollback只回滚最内部的事务时,你就可以结束具有外部结果和部分保存(如第一个示例中的那样,即失败).
我认为你不能这样做,after_save你应该看看around_save:
def around_save
ActiveRecord::Base.transaction do
yield # calls the actual save method
raise ActiveRecord::Rollback if my_condition?
end
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6551 次 |
| 最近记录: |