FR: Inspecting old state of ActiveRecord object "before `changes`"

Sometimes it’s nice to be able to access a version of an ActiveRecord object before certain changes are applied, e.g.:

class Foo < ActiveRecord::Base
   def foobar
      some_attribute
   end

   around_update :bar
   def bar
      pp self.foobar # At this point, I'd like to be able to inspect the 'old' state
      yield
      pp self.foobar
   end
end

Currently, ActiveRecord::Dirty provides some methods to inspect changes and older values of specific attributes through changes and *_was, but not the entire previous state. Having access to it would allow you to call instance methods using the old state.

I propose to add the following instance method to ActiveRecord::Dirty:

def self_was
  self.changes.each_with_object(self.dup) {|(attribute,(previous_value,_)), object|
    object.write_attribute(attribute, previous_value)
  }
end

So we can replace self by self_was before the yield and get the behavior that we want.

Heads up: I will probably not look back at this topic, as I’ve already opted to use this feature in my own repo. This is just my two cents on a missing feature in ActiveRecord::Dirty. Initially posted it as an issue (Inspecting old state of ActiveRecord object "before `changes`" · Issue #48243 · rails/rails · GitHub), but got redirected here.

1 Like

The use-case where I’m applying this personally is inside a method that checks differences among some complicated queries between the old and new object, and to send push events based on those differences.