module ActiveRecord::AttributeMethods::Dirty

Private Instance Methods

_field_changed?(attr, old, value) click to toggle source
# File lib/active_record/attribute_methods/dirty.rb, line 80
def _field_changed?(attr, old, value)
  if column = column_for_attribute(attr)
    if column.number? && (changes_from_nil_to_empty_string?(column, old, value) ||
                          changes_from_zero_to_string?(old, value))
      value = nil
    else
      value = column.type_cast(value)
    end
  end

  old != value
end
changes_from_nil_to_empty_string?(column, old, value) click to toggle source
# File lib/active_record/attribute_methods/dirty.rb, line 97
def changes_from_nil_to_empty_string?(column, old, value)
  # For nullable numeric columns, NULL gets stored in database for blank (i.e. '') values.
  # Hence we don't record it as a change if the value changes from nil to ''.
  # If an old value of 0 is set to '' we want this to get changed to nil as otherwise it'll
  # be typecast back to 0 (''.to_i => 0)
  column.null && (old.nil? || old == 0) && value.blank?
end
changes_from_zero_to_string?(old, value) click to toggle source
# File lib/active_record/attribute_methods/dirty.rb, line 105
def changes_from_zero_to_string?(old, value)
  # For columns with old 0 and value non-empty string
  old == 0 && value.is_a?(String) && value.present? && value != '0'
end
clone_with_time_zone_conversion_attribute?(attr, old) click to toggle source
# File lib/active_record/attribute_methods/dirty.rb, line 93
def clone_with_time_zone_conversion_attribute?(attr, old)
  old.class.name == "Time" && time_zone_aware_attributes && !self.skip_time_zone_conversion_for_attributes.include?(attr.to_sym)
end
update(*) click to toggle source
Calls superclass method
# File lib/active_record/attribute_methods/dirty.rb, line 70
def update(*)
  if partial_updates?
    # Serialized attributes should always be written in case they've been
    # changed in place.
    super(changed | (attributes.keys & self.class.serialized_attributes.keys))
  else
    super
  end
end
write_attribute(attr, value) click to toggle source

Wrap #write_attribute to remember original attribute value.

# File lib/active_record/attribute_methods/dirty.rb, line 52
def write_attribute(attr, value)
  attr = attr.to_s

  # The attribute already has an unsaved change.
  if attribute_changed?(attr)
    old = @changed_attributes[attr]
    @changed_attributes.delete(attr) unless _field_changed?(attr, old, value)
  else
    old = clone_attribute_value(:read_attribute, attr)
    # Save Time objects as TimeWithZone if time_zone_aware_attributes == true
    old = old.in_time_zone if clone_with_time_zone_conversion_attribute?(attr, old)
    @changed_attributes[attr] = old if _field_changed?(attr, old, value)
  end

  # Carry on.
  super(attr, value)
end