在ActiveRecord模型中after_save回调我需要ROLLBACK事务并返回false。在after_save回调中返回false和回滚
def after_save_callback
if mycondition?
raise ActiveRecord::Rollback
end
end
此回调回滚事务,但mymodel.save!返回true。如何让它返回false和回滚?
在ActiveRecord模型中after_save回调我需要ROLLBACK事务并返回false。在after_save回调中返回false和回滚
def after_save_callback
if mycondition?
raise ActiveRecord::Rollback
end
end
此回调回滚事务,但mymodel.save!返回true。如何让它返回false和回滚?
我不认为你可以做到这一点与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
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
再次wrapp(不喜欢在最后一个例子),因为轨道将包装调用around_save
与自己是如此ActiveRecord::Base.transaction
当你raise ActiveRecord::Rollback
你只回滚最内部交易,所以你可以结束extrange结果和部分保存(如在第一个例子中,这是失败)。
如果要中止在after_save
回调保存,你应该
raise ActiveRecord::RecordInvalid.new(self)
而不是
raise ActiveRecord::Rollback
这不仅会回滚事务(回调总是possibly-内发生作为save
或create
的一部分的隐式交易),但也导致save
返回false
。
下面是更细节的文章:在一个事务中http://tech.taskrabbit.com/blog/2013/05/23/rollback-after-save/
Rails的包装'型号save'反正。你不应该在around_save钩子里面打开第二个事务。相反,你应该提高'ActiveRecord :: Rollback'。 – BBonifield 2013-01-10 00:48:08