Callback for changed ActiveRecord attributes? Callback for changed ActiveRecord attributes? ruby-on-rails ruby-on-rails

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.