是否所有作业都是通过Ruby / Rails中的setter完成的?

时间:2013-01-29 14:18:13

标签: ruby-on-rails

我有一个与另一个模型有belongs_to关系的Rails模型。

class Foo < ActiveRecord::Base
  belongs_to :bar
end

每次bar设置/更新foo我想要“拦截”修改后的更改并更新foo上的内容。

我的猜测是,我可以覆盖bar的setter并按照我的意愿行事。但是,由于我对Ruby / Rails相对较新,我担心的是bar可以在foo设置的“{魔法”方式,而不是通过我的二传手(也许)使用mass-assignment,update / update_all调用等)。

确保对bar的任何更改运行一个代码块以对此更改做出反应的最安全的方法是什么?

2 个答案:

答案 0 :(得分:1)

根据您的需要,您可以使用条形图上的回调来执行foo上的特定代码。

您需要的所有文档都在http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

例如:

class Bar < ActiverRecord::Base
    has_many :foos
    before_save :do_something

    private
        def do_something
            self.foos.each {|f| f.update_attribute('bar_has_changed', true) }
        end
end

答案 1 :(得分:1)

覆盖bar的setter并不是一个好主意。

案例:

class Foo < ActiveRecord::Base
  belongs_to :bar

  def bar=(value)
    # do nothing
  end
end

f = Foo.create
b = Bar.create
f.update_attributes(bar_id: b.id)
f.bar
# => #<Bar id: 1, ... >

虽然bar setter已被覆盖,因此它什么都不做,但你可以很容易地绕过它。您在Foo上实现的任何自定义更新都是如此:在这种情况下,更新关联时不会调用它。

改为使用回调。