回调更改的ActiveRecord属性?

我知道ActiveRecord :: Dirty和相关的方法,但我没有看到我可以订阅属性更改事件的方法。 就像是:

class Person < ActiveRecord::Base def attribute_changed(attribute_name, old_value, new_value) end #or attribute_changed do |attribute_name, old_value, new_value| end end 

是否有Rails标准或插件? 我觉得它必定存在于某个地方,我只是想念它。

cwninja的答案应该可以解决问题,但还有更多的内容。

首先,使用write_attribute方法完成基本属性处理,因此您应该使用它。

Rails也有一个内置的回调结构,尽管它不允许传递有点烦人的参数,但它可能很好用。

使用自定义回调你可以这样做:

 class Person < ActiveRecord::Base def write_attribute(attr_name, value) attribute_changed(attr_name, read_attribute(attr_name), value) super end private def attribute_changed(attr, old_val, new_val) logger.info "Attribute Changed: #{attr} from #{old_val} to #{new_val}" end end 

如果你想尝试使用Rails回调(特别是如果你可能有多个回调和/或子类),你可以这样做:

 class Person < ActiveRecord::Base define_callbacks :attribute_changed attribute_changed :notify_of_attribute_change def write_attribute(attr_name, value) returning(super) do @last_changed_attr = attr_name run_callbacks(:attribute_changed) end end private def notify_of_attribute_change attr = @last_changed_attr old_val, new_val = send("#{attr}_change") logger.info "Attribute Changed: #{attr} from #{old_val} to #{new_val}" end end 

对于Rails 3:

 class MyModel < ActiveRecord::Base after_update :my_listener, :if => :my_attribute_changed? def my_listener puts "Attribute 'my_attribute' has changed" end end 

评论: https : //stackoverflow.com/a/1709956/316700

我没有找到关于此的官方文档。

对于Rails 4

 def attribute=(value) super(value) your_callback(self.attribute) end 

如果你想覆盖属性的值,你应该使用write_attribute(:attribute, your_callback(self.attribute))而不是attribute=或者你将循环遍历它,直到你得到一个堆栈太深的exception。

尝试:

 def attribute_changed(attribute_name, old_value, new_value) end def attribute=(attribute_name, value) returning(super) do attribute_changed(attribute_name, attribute_was(attribute_name), attribute(attribute_name)) end end 

刚刚发明了这个,但它应该工作。

你总是可以访问私有方法changed_attributes并使用before_save检查那里的密钥并按照你的意愿去做。

我发现最简单的方法:

 after_save :my_method, :if => Proc.new{ self.my_attribute_changed? } def my_method ... do stuff... end