如何避免ActiveRecord模型双重保存?
型号“一”
class One < ActiveRecord::Base before_save :do_stuff private def do_stuff two = Two.find(8) two.field2 = 'Value' two.save! end end
型号“两个”
class Two < ActiveRecord::Base before_save :do_stuff private def do_stuff one = One.find(7) one.field2 = 'SomeValue' one.save! end end
执行:
two = Two.find(1) two.somefield = 'NewVal' two.save!
无限循环将开始。 什么是ruby-on-rails方式实现两个必须在before_save回调中互相改变的模型?
在极少数情况下,您需要执行此操作,您可能希望使用attr_accessor
禁用before_save
filter,或将其移至after_save
块以避免循环。
例如:
class One < ActiveRecord::Base attr_accessor :not_doing_stuff before_save :do_stuff, :unless => :not_doing_stuff private def do_stuff two = Two.find(8) two.field2 = 'Value' two.save! end end
您至少在其中一个上禁用了触发器:
class Two < ActiveRecord::Base before_save :do_stuff private def do_stuff one = One.find(7) one.not_doing_stuff = true one.field2 = 'SomeValue' one.save! end end
像这样的事情总是非常难看,所以尽量避免它,除非你能想到别的办法。 如果您需要它,请确保您已经编写了足够的unit testing,以确保在某些边缘情况下它不会锁定到无限循环。
不要在before_save中调用save
:它将触发无限循环。 返回true或false – 如果你在before_save中输入的内容成功,则返回true,如果失败则返回false。 返回false将取消保存和所有其他回调。