如何避免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_savefilter,或将其移至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将取消保存和所有其他回调。