123456789_123456789_123456789_123456789_123456789_

Module: Mongoid::Changeable

Relationships & Source Files
Namespace Children
Modules:
Classes:
Extension / Inclusion / Inheritance Descendants
Included In:
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, ActiveSupport::Concern
Defined in: lib/mongoid/changeable.rb

Overview

Defines behavior for dirty tracking.

Constant Summary

Instance Attribute Summary

Instance Method Summary

Instance Attribute Details

#changedArray<String> (readonly)

Get the changed attributes for the document.

Examples:

Get the changed attributes.

model.changed

Returns:

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 14
def changed
  changed_attributes.keys.select { |attr| attribute_change(attr) }
end

#changed?true | false (readonly)

Has the document changed?

Examples:

Has the document changed?

model.changed?

Returns:

  • (true | false)

    If the document is changed.

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 24
def changed?
  changes.values.any? { |val| val } || children_changed?
end

#children_changed?true | false (readonly)

Note:

This intentionally only considers children and not descendants.

Have any children (embedded documents) of this document changed?

Returns:

  • (true | false)

    If any children have changed.

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 33
def children_changed?
  _children.any?(&:changed?)
end

Instance Method Details

#attribute_before_last_save(attr) ⇒ Object

Returns the original value of an attribute before the last save.

This method is useful in after callbacks to get the original value of

an attribute before the save that triggered the callbacks to run.

Parameters:

Returns:

  • (Object)

    Value of the attribute before the last save.

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 141
def attribute_before_last_save(attr)
  attr = database_field_name(attr)
  attributes_before_last_save[attr]
end

#attribute_change(attr) ⇒ Array<Object> (private)

Get the old and new value for the provided attribute.

Examples:

Get the attribute change.

model.attribute_change("name")

Parameters:

  • attr (String)

    The name of the attribute.

Returns:

  • (Array<Object>)

    The old and new values.

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 219
def attribute_change(attr)
  attr = database_field_name(attr)
  [ changed_attributes[attr], attributes[attr] ] if attribute_changed?(attr)
end

#attribute_changed?(attr, from: ATTRIBUTE_UNCHANGED, to: ATTRIBUTE_UNCHANGED) ⇒ true | false

Determine if a specific attribute has changed.

Examples:

Has the attribute changed?

model.attribute_changed?("name")

Parameters:

  • attr (String)

    The name of the attribute.

  • from (Object)

    The object the attribute was changed from (optional).

  • to (Object)

    The object the attribute was changed to (optional).

Returns:

  • (true | false)

    Whether the attribute has changed.

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 257
def attribute_changed?(attr, from: ATTRIBUTE_UNCHANGED, to: ATTRIBUTE_UNCHANGED)
  attr = database_field_name(attr)
  return false unless changed_attributes.key?(attr)
  return false if changed_attributes[attr] == attributes[attr]
  return false if from != changed_attributes[attr]
  return false if to != attributes[attr]

  true
end

#attribute_changed_from_default?(attr) ⇒ true | false

Get whether or not the field has a different value from the default.

Examples:

Is the field different from the default?

model.attribute_changed_from_default?

Parameters:

  • attr (String)

    The name of the attribute.

Returns:

  • (true | false)

    If the attribute differs.

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 275
def attribute_changed_from_default?(attr)
  return false unless (field = fields[attr])

  attributes[attr] != field.eval_default(self)
end

#attribute_previously_was(attr) ⇒ Object | nil

Get the previous attribute value that was changed before the document was saved.

It the document has not been saved yet, or was just loaded from database, this method returns nil for all attributes.

Parameters:

  • attr (String)

    The attribute name.

Returns:

  • (Object | nil)

    Attribute value before the document was saved, or nil if the document has not been saved yet.

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 302
def attribute_previously_was(attr)
  attr = database_field_name(attr)
  if previous_changes.key?(attr)
    previous_changes[attr].first
  else
    previous_attributes[attr]
  end
end

#attribute_was(attr)

Get the previous value for the attribute.

Examples:

Get the previous value.

model.attribute_was("name")

Parameters:

  • attr (String)

    The attribute name.

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 287
def attribute_was(attr)
  attr = database_field_name(attr)
  attribute_changed?(attr) ? changed_attributes[attr] : attributes[attr]
end

#attribute_will_change!(attr) ⇒ Object

Flag an attribute as going to change.

Examples:

Flag the attribute.

model.attribute_will_change!("name")

Parameters:

  • attr (String)

    The name of the attribute.

Returns:

  • (Object)

    The old value.

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 319
def attribute_will_change!(attr)
  return if changed_attributes.key?(attr)

  changed_attributes[attr] = read_raw_attribute(attr).__deep_copy__
end

#attributes_before_last_save (private)

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 207
def attributes_before_last_save
  @attributes_before_last_save ||= {}
end

#changed_attributesHash<String, Object>

Get the attribute changes.

Examples:

Get the attribute changes.

model.changed_attributes

Returns:

  • (Hash<String, Object>)

    The attribute changes.

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 43
def changed_attributes
  @changed_attributes ||= {}
end

#changesHash<String, Array<Object, Object> ] The changes.

Get all the changes for the document.

Examples:

Get all the changes.

model.changes

Returns:

  • (Hash<String, Array<Object, Object> ] The changes.)

    Hash<String, Array<Object, Object> ] The changes.

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 53
def changes
  changed.each_with_object({}) do |attr, changes|
    change = attribute_change(attr)
    changes[attr] = change if change
  end.with_indifferent_access
end

#changes_before_last_save (private)

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 203
def changes_before_last_save
  @changes_before_last_save ||= {}
end

#move_changes

Call this method after save, so the changes can be properly switched.

This will unset the memoized children array, set new record flag to false, set the document as validated, and move the dirty changes.

Examples:

Move the changes to previous.

person.move_changes
[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 67
def move_changes
  @changes_before_last_save = @previous_changes
  @previous_changes = changes
  @attributes_before_last_save = @previous_attributes
  @previous_attributes = attributes.dup
  reset_atomic_updates!
  changed_attributes.clear
end

#post_persist

Things that need to execute after a document has been persisted.

Examples:

Handle post persistence.

document.post_persist
[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 80
def post_persist
  reset_persisted_descendants
  reset_attributes_before_type_cast
  move_changes
end

#previous_attributesHash (private)

Get attributes of the document before the document was saved.

Returns:

  • (Hash)

    Previous attributes

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 199
def previous_attributes
  @previous_attributes ||= {}
end

#previous_changesHash<String, Array<Object, Object> ] The previous changes.

Get the previous changes on the document.

Examples:

Get the previous changes.

model.previous_changes

Returns:

  • (Hash<String, Array<Object, Object> ] The previous changes.)

    Hash<String, Array<Object, Object> ] The previous changes.

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 92
def previous_changes
  @previous_changes ||= {}
end

#remove_change(name)

Remove a change from the dirty attributes hash. Used by the single field atomic updaters.

Examples:

Remove a flagged change.

model.remove_change(:field)

Parameters:

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 103
def remove_change(name)
  changed_attributes.delete(name.to_s)
end

#reset_attribute!(attr) ⇒ Object

::Set the attribute back to its old value.

Examples:

Reset the attribute.

model.reset_attribute!("name")

Parameters:

  • attr (String)

    The name of the attribute.

Returns:

  • (Object)

    The old value.

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 333
def reset_attribute!(attr)
  attr = database_field_name(attr)
  attributes[attr] = changed_attributes.delete(attr) if attribute_changed?(attr)
end

#reset_attribute_to_default!(attr)

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 338
def reset_attribute_to_default!(attr)
  attr = database_field_name(attr)
  if (field = fields[attr])
    __send__("#{attr}=", field.eval_default(self))
  else
    __send__("#{attr}=", nil)
  end
end

#reset_attributes_before_type_cast

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 347
def reset_attributes_before_type_cast
  @attributes_before_type_cast = @attributes.dup
end

#saved_change_to_attribute(attr) ⇒ Array<Object> | nil

Returns the change to an attribute during the last save.

Parameters:

Returns:

  • (Array<Object> | nil)

    If the attribute was changed, returns an array containing the original value and the saved value, otherwise nil.

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 152
def saved_change_to_attribute(attr)
  attr = database_field_name(attr)
  previous_changes[attr]
end

#saved_change_to_attribute?(attr, from: Utils::PLACEHOLDER, to: Utils::PLACEHOLDER) ⇒ true | false

Returns whether this attribute changed during the last save.

This method is useful in after callbacks, to see the change

in an attribute during the save that triggered the callbacks to run.

Parameters:

  • attr (String)

    The name of the attribute.

  • from (Object)

    The object the attribute was changed from (optional).

  • to (Object)

    The object the attribute was changed to (optional).

Returns:

  • (true | false)

    Whether the attribute has changed during the last save.

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 167
def saved_change_to_attribute?(attr, from: Utils::PLACEHOLDER, to: Utils::PLACEHOLDER)
  changes = saved_change_to_attribute(attr)
  return false unless changes.is_a?(Array)

  return true if Utils.placeholder?(from) && Utils.placeholder?(to)
  return changes.first == from if Utils.placeholder?(to)
  return changes.last == to if Utils.placeholder?(from)

  changes.first == from && changes.last == to
end

#settersHash

Gets all the new values for each of the changed fields, to be passed to a MongoDB $set modifier.

Examples:

Get the setters for the atomic updates.

person = Person.new(:title => "Sir")
person.title = "Madam"
person.setters # returns { "title" => "Madam" }

Returns:

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 116
def setters
  mods = {}
  changes.each_pair do |name, changes|
    next unless changes

    old, new = changes
    field = fields[name]
    key = atomic_attribute_name(name)
    if field&.resizable?
      field.add_atomic_changes(self, name, key, mods, new, old)
    else
      mods[key] = new unless atomic_unsets.include?(key)
    end
  end
  mods
end

#will_save_change_to_attribute?(attr, **kwargs) ⇒ true | false

Returns whether this attribute change the next time we save.

This method is useful in validations and before callbacks to determine

if the next call to save will change a particular attribute.

Parameters:

  • attr (String)

    The name of the attribute.

  • **kwargs

    The optional keyword arguments.

Returns:

  • (true | false)

    Whether the attribute change the next time we save.

[ GitHub ]

  
# File 'lib/mongoid/changeable.rb', line 190
def will_save_change_to_attribute?(attr, **kwargs)
  attribute_changed?(attr, **kwargs)
end