Callback for changed ActiveRecord attributes?
cwninja's answer should do the trick, but there is a little bit more to it.
First of all, the base attribute handling is done with the write_attribute method so you should be tapping into this.
Rails also does have a built in callback structure which could be nice to tap into though it doesn't allow for passing arguments which is a bit of an annoyance.
Using custom callbacks you could do it like this:
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
If you wanted to try to use Rails callbacks (especially useful if you might have multiple callbacks and/or subclassing) you could do something like this:
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}" endend
For Rails 3:
class MyModel < ActiveRecord::Base after_update :my_listener, :if => :my_attribute_changed? def my_listener puts "Attribute 'my_attribute' has changed" endend
Commented in: https://stackoverflow.com/a/1709956/316700
I don't find official documentation about this.
For Rails 4
def attribute=(value) super(value) your_callback(self.attribute)end
If you want to overwrite the value of attribute you should use write_attribute(:attribute, your_callback(self.attribute))
and not attribute=
or you'll loop over it until you get a stack too deep exception.