module ActiveModel::Dirty

def as_json(options = {}) # :nodoc:

:nodoc:
def as_json(options = {}) # :nodoc:
  options[:except] = [*options[:except], "mutations_from_database", "mutations_before_last_save"]
  super(options)
end

def attribute_change(attr_name)

Dispatch target for *_change attribute methods.
def attribute_change(attr_name)
  mutations_from_database.change_to_attribute(attr_name.to_s)
end

def attribute_changed?(attr_name, **options) # :nodoc:

:nodoc:
Dispatch target for *_changed? attribute methods.
def attribute_changed?(attr_name, **options) # :nodoc:
  mutations_from_database.changed?(attr_name.to_s, **options)
end

def attribute_changed_in_place?(attr_name) # :nodoc:

:nodoc:
def attribute_changed_in_place?(attr_name) # :nodoc:
  mutations_from_database.changed_in_place?(attr_name.to_s)
end

def attribute_previous_change(attr_name)

Dispatch target for *_previous_change attribute methods.
def attribute_previous_change(attr_name)
  mutations_before_last_save.change_to_attribute(attr_name.to_s)
end

def attribute_previously_changed?(attr_name, **options) # :nodoc:

:nodoc:
Dispatch target for *_previously_changed? attribute methods.
def attribute_previously_changed?(attr_name, **options) # :nodoc:
  mutations_before_last_save.changed?(attr_name.to_s, **options)
end

def attribute_previously_was(attr_name) # :nodoc:

:nodoc:
Dispatch target for *_previously_was attribute methods.
def attribute_previously_was(attr_name) # :nodoc:
  mutations_before_last_save.original_value(attr_name.to_s)
end

def attribute_was(attr_name) # :nodoc:

:nodoc:
Dispatch target for *_was attribute methods.
def attribute_was(attr_name) # :nodoc:
  mutations_from_database.original_value(attr_name.to_s)
end

def attribute_will_change!(attr_name)

Dispatch target for *_will_change! attribute methods.
def attribute_will_change!(attr_name)
  mutations_from_database.force_change(attr_name.to_s)
end

def changed

person.changed # => ["name"]
person.name = 'bob'
person.changed # => []

Returns an array with the name of the attributes with unsaved changes.
def changed
  mutations_from_database.changed_attribute_names
end

def changed?

person.changed? # => true
person.name = 'bob'
person.changed? # => false

Returns +true+ if any of the attributes has unsaved changes, +false+ otherwise.
def changed?
  mutations_from_database.any_changes?
end

def changed_attributes

person.changed_attributes # => {"name" => "bob"}
person.name = 'robert'
person.name # => "bob"

values like attr => original value.
Returns a hash of the attributes with unsaved changes indicating their original
def changed_attributes
  mutations_from_database.changed_values
end

def changes

person.changes # => { "name" => ["bill", "bob"] }
person.name = 'bob'
person.changes # => {}

and new values like attr => [original value, new value].
Returns a hash of changed attributes indicating their original
def changes
  mutations_from_database.changes
end

def changes_applied

+mutations_from_database+ to +mutations_before_last_save+ respectively.
Clears dirty data and moves +changes+ to +previous_changes+ and
def changes_applied
  unless defined?(@attributes)
    mutations_from_database.finalize_changes
  end
  @mutations_before_last_save = mutations_from_database
  forget_attribute_assignments
  @mutations_from_database = nil
end

def clear_attribute_change(attr_name)

def clear_attribute_change(attr_name)
  mutations_from_database.forget_change(attr_name.to_s)
end

def clear_attribute_changes(attr_names)

def clear_attribute_changes(attr_names)
  attr_names.each do |attr_name|
    clear_attribute_change(attr_name)
  end
end

def clear_changes_information

Clears all dirty data: current changes and previous changes.
def clear_changes_information
  @mutations_before_last_save = nil
  forget_attribute_assignments
  @mutations_from_database = nil
end

def forget_attribute_assignments

def forget_attribute_assignments
  @attributes = @attributes.map(&:forgetting_assignment) if defined?(@attributes)
end

def initialize_dup(other) # :nodoc:

:nodoc:
def initialize_dup(other) # :nodoc:
  super
  if self.class.respond_to?(:_default_attributes)
    @attributes = self.class._default_attributes.map do |attr|
      attr.with_value_from_user(@attributes.fetch_value(attr.name))
    end
  end
  @mutations_from_database = nil
end

def mutations_before_last_save

def mutations_before_last_save
  @mutations_before_last_save ||= ActiveModel::NullMutationTracker.instance
end

def mutations_from_database

def mutations_from_database
  @mutations_from_database ||= if defined?(@attributes)
    ActiveModel::AttributeMutationTracker.new(@attributes)
  else
    ActiveModel::ForcedMutationTracker.new(self)
  end
end

def previous_changes

person.previous_changes # => {"name" => ["bob", "robert"]}
person.save
person.name = 'robert'
person.name # => "bob"

Returns a hash of attributes that were changed before the model was saved.
def previous_changes
  mutations_before_last_save.changes
end

def restore_attribute!(attr_name)

Dispatch target for restore_*! attribute methods.
def restore_attribute!(attr_name)
  attr_name = attr_name.to_s
  if attribute_changed?(attr_name)
    __send__("#{attr_name}=", attribute_was(attr_name))
    clear_attribute_change(attr_name)
  end
end

def restore_attributes(attr_names = changed)

Restore all previous data of the provided attributes.
def restore_attributes(attr_names = changed)
  attr_names.each { |attr_name| restore_attribute!(attr_name) }
end