如何避免ActiveRecord模型双省电? [英] How to avoid ActiveRecord model double saving?

查看:134
本文介绍了如何避免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-轨道的方式来实现两种模式,必须改变对方before_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?

推荐答案

在你需要做这样的希望极少数情况下,您可能需要使用禁用的 before_save 过滤器一个 attr_accessor ​​或将其移动到 after_save的块,以避免循环。

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.

例如:

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.

这篇关于如何避免ActiveRecord模型双省电?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆