def values_changed?
      unless tracked_attributes.present?
        raise TrackChangesError, 'Object has not been configured for change tracking.'
      end

      changed = marked_for_destruction? ? true : false
      tracked_attributes.each do |attr|
        break if changed

        changed = send(attr) != send("#{attr}_was") if send("#{attr}_changed?")
      end
      self.exclude_from_save = !changed
      changed
    end
def values_changed?
      unless tracked_attributes.present?
        raise TrackChangesError, 'Object has not been configured for change tracking.'
      end

      changed = marked_for_destruction? ? true : false
      tracked_attributes.each do |attr|
        break if changed

        changed = send(attr) != send("#{attr}_was") if send("#{attr}_changed?")
      end
      self.exclude_from_save = !changed
      changed
    end
Determines if any attribute values have changed using ActiveModel::Dirty.
 For attributes enabled for change tracking compares changed values. All values
 submitted from an HTML form are strings, thus a string of 25.0 doesn't match an
 original float of 25.0. Call this method after valid? to allow for any type coercing
 occurring before saving to datastore.

 Consider the scenario in which the user submits an unchanged form value named `area`.
 The initial value from datastore is a float of 25.0, which during assign_attributes
 is set to a string of '25.0'. It is then coerced back to a float of 25.0 during a
 validation callback. The area_changed? will return true, yet the value is back where
 is started.

 For example:

   class Shapes
     include ActiveModel::Datastore

     attr_accessor :area
     enable_change_tracking :area
     after_validation :format_values

     def format_values
       format_property_value :area, :float
     end

     def update(params)
       assign_attributes(params)
       if valid?
         puts values_changed?
         puts area_changed?
         p area_change
       end
     end
   end

 Will result in this:
   values_changed? false
   area_changed? true # This is correct, as area was changed but the value is identical.
   area_change [0, 0]

 If none of the tracked attributes have changed, the `exclude_from_save` attribute is
 set to true and the method returns false.