在ActiveRecord模型中,after_save回调我需要ROLLBACK事务并返回false。
def after_save_callback
if mycondition?
raise ActiveRecord::Rollback
end
end
这个回调回滚事务但mymodel.save!返回true。如何让它返回false和rollback?
答案 0 :(得分:9)
如果要在after_save
回调中中止保存,则应该
raise ActiveRecord::RecordInvalid.new(self)
而不是
raise ActiveRecord::Rollback
这不仅会回滚事务(回调总是发生在可能隐式事务中作为save
或create
的一部分),还会导致save
返回{{1 }}
以下是一篇详细介绍的文章:http://tech.taskrabbit.com/blog/2013/05/23/rollback-after-save/
答案 1 :(得分:5)
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
所以...我认为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
编辑:阅读我写的内容......现在看起来很难理解。重点是:如果您要使用aroud_save
,请不要再使用ActiveRecord::Base.transaction
(在上一个示例中执行>),因为rails会将调用包装到{{1使用自己的around_save
,所以当你ActiveRecord::Base.transaction
只回滚最内部的事务时,你可以用outnge结果和部分保存结束(就像在第一个例子中那样失败强>)。
答案 2 :(得分:-1)
我不认为您可以使用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