Track dirty for not-persisted attribute in an ActiveRecord object in rails

ActiveRecord has the #attribute method (source) which once invoked from your class will let ActiveModel::Dirty to create methods such as bar_was, bar_changed?, and many others.

Thus you would have to call attribute :bar within any class that extends from ActiveRecord (or ApplicationRecord for most recent versions of Rails) in order to create those helper methods upon bar.

Edit: Note that this approach should not be mixed with attr_accessor :bar

Edit 2: Another note is that unpersisted attributes defined with attribute (eg attribute :bar, :string) will be blown away on save. If you need attrs to hang around after save (as I did), you actually can (carefully) mix with attr_reader, like so:

attr_reader :bar
attribute :bar, :string

def bar=(val)
  super
  @bar = val
end

I'm using the attribute_will_change! method and things seem to be working fine.

It's a private method defined in active_model/dirty.rb, but ActiveRecord mixes it in all models.

This is what I ended up implementing in my model class:

def bar
  @bar ||= init_bar
end
def bar=(value)
  attribute_will_change!('bar') if bar != value
  @bar = value
end
def bar_changed?
  changed.include?('bar')
end

The init_bar method is just used to initialise the attribute. You may or may not need it.

I didn't need to specify any other method (such as define_attribute_methods) or include any modules. You do have to reimplement some of the methods yourself, but at least the behaviour will be mostly consistent with ActiveModel.

I admit I haven't tested it thoroughly yet, but so far I've encountered no issues.