如果我将一个after_save回调添加到ActiveRecord模型,并且在该回调上我使用update_attribute来更改对象,则再次调用回调,因此发生"堆栈溢出"(hehe,无法抗拒).
是否可以避免这种行为,可能在执行期间禁用回调?或者还有另一种方法吗?
谢谢!
一种解决方法是在类中设置变量,并在after_save中检查其值.
先检查一下.(如果var)
在调用update_attribute之前将其分配给'false'值.
调用update_attribute.
将其指定为"true"值.
结束
这样,它只会尝试保存两次.这可能会两次打到您的数据库,这可能是也可能不是.
我有一种模糊的感觉,内置了一些东西,但这是一种相当简单的方法来防止几乎任何应用程序中的特定递归点.我还建议再次查看代码,因为很可能无论你在after_save中做什么都应该在before_save中完成.有时候这不是真的,但它们相当罕见.
你可以使用before_save回调吗?
我没有看到这个答案,所以我想我会添加它,以防它帮助任何人搜索这个主题.(ScottD的no_callbacks建议很接近.)
ActiveRecord提供update_without_callbacks
了这种情况,但它是一种私有方法.无论如何,使用send来访问它.在你正在保存的对象的回调中正是使用它的原因.
另外还有另一个SO线程可以很好地解决这个问题: 如何避免运行ActiveRecord回调?
您还可以查看插件Without_callbacks.它为AR添加了一个方法,允许您跳过给定块的某些回调.例:
def your_after_save_func YourModel.without_callbacks(:your_after_save_func) do Your updates/changes end end
了解如何实现update_attribute.改为使用send方法:
send(name.to_s + '=', value)