How to avoid ActiveRecord model double saving?

狂风中的少年 提交于 2019-12-11 01:05:39

问题


Model "One"

class One < ActiveRecord::Base
  before_save :do_stuff

  private
    def do_stuff
      two = Two.find(8)
      two.field2 = 'Value'
      two.save!
    end
end

Model "Two"

class Two < ActiveRecord::Base
  before_save :do_stuff

  private
    def do_stuff
      one = One.find(7)
      one.field2 = 'SomeValue'
      one.save!
    end
end

Executing:

two = Two.find(1)
two.somefield = 'NewVal'
two.save!

Infinite loop will start. What would be most ruby-on-rails way to implement two models that must change each other on before_save callback?


回答1:


On the hopefully rare occasions you need to do this, you might want to disable your before_save filter using an attr_accessor or move it to an after_save block to avoid looping.

For example:

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

You'd disable the trigger on at least one of them:

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

Things like this are always very ugly, so try and avoid it unless you can think of no other way. If you need it, make sure you've written enough unit tests to ensure it won't lock into an endless loop under some edge cases.




回答2:


Don't call save in before_save: it will trigger an infinite loop. Return true or false instead -- true if whatever you put in the before_save succeeded, false if it failed. Returning false will cancel the save and all other callbacks.



来源:https://stackoverflow.com/questions/9703797/how-to-avoid-activerecord-model-double-saving

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!