Module: Mongoid::Changeable

Extended by:
ActiveSupport::Concern
Included in:
Composable
Defined in:
lib/mongoid/changeable.rb

Overview

Defines behavior for dirty tracking.

Defined Under Namespace

Modules: ClassMethods Classes: Anything

Instance Method Summary collapse

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:

  • attr (Symbol | String)

    The name of the attribute.

Returns:

  • (Object)

    Value of the attribute before the last save.



150
151
152
153
# File 'lib/mongoid/changeable.rb', line 150

def attribute_before_last_save(attr)
  attr = database_field_name(attr)
  attributes_before_last_save[attr]
end

#changedArray<String>

Get the changed attributes for the document.

Examples:

Get the changed attributes.

model.changed

Returns:

  • (Array<String>)

    The changed attributes.



14
15
16
# File 'lib/mongoid/changeable.rb', line 14

def changed
  changed_attributes.keys.select { |attr| attribute_change(attr) }
end

#changed?true | false

Has the document changed?

Examples:

Has the document changed?

model.changed?

Returns:

  • (true | false)

    If the document is changed.



32
33
34
# File 'lib/mongoid/changeable.rb', line 32

def changed?
  changes.values.any? { |val| val } || children_changed?
end

#changed_attributesHash<String, Object>

Get the attribute changes.

Examples:

Get the attribute changes.

model.changed_attributes

Returns:

  • (Hash<String, Object>)

    The attribute changes.



51
52
53
# File 'lib/mongoid/changeable.rb', line 51

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.



61
62
63
64
65
66
# File 'lib/mongoid/changeable.rb', line 61

def changes
  changed.each_with_object({}) do |attr, changes|
    change = attribute_change(attr)
    changes[attr] = change if change
  end.with_indifferent_access
end

#children_changed?true | false

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.



41
42
43
# File 'lib/mongoid/changeable.rb', line 41

def children_changed?
  @children_may_have_changed || _children.any?(&:changed?)
end

#children_may_have_changed!Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Indicates that the children of this document may have changed, and ought to be checked when the document is validated.



22
23
24
# File 'lib/mongoid/changeable.rb', line 22

def children_may_have_changed!
  @children_may_have_changed = true
end

#move_changesObject

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


75
76
77
78
79
80
81
82
83
# File 'lib/mongoid/changeable.rb', line 75

def move_changes
  @changes_before_last_save = @previous_changes
  @previous_changes = changes
  @attributes_before_last_save = @previous_attributes
  @previous_attributes = attributes.dup
  @children_may_have_changed = false
  reset_atomic_updates!
  changed_attributes.clear
end

#post_persistObject

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

Examples:

Handle post persistence.

document.post_persist


89
90
91
92
93
# File 'lib/mongoid/changeable.rb', line 89

def post_persist
  reset_persisted_descendants
  reset_attributes_before_type_cast
  move_changes
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.



101
102
103
# File 'lib/mongoid/changeable.rb', line 101

def previous_changes
  @previous_changes ||= {}
end

#remove_change(name) ⇒ Object

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:

  • name (Symbol | String)

    The name of the field.



112
113
114
# File 'lib/mongoid/changeable.rb', line 112

def remove_change(name)
  changed_attributes.delete(name.to_s)
end

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

Returns the change to an attribute during the last save.

Parameters:

  • attr (Symbol | String)

    The name of the attribute.

Returns:

  • (Array<Object> | nil)

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



161
162
163
164
# File 'lib/mongoid/changeable.rb', line 161

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) (defaults to: Utils::PLACEHOLDER)

    The object the attribute was changed from (optional).

  • to (Object) (defaults to: Utils::PLACEHOLDER)

    The object the attribute was changed to (optional).

Returns:

  • (true | false)

    Whether the attribute has changed during the last save.



176
177
178
179
180
181
182
183
184
185
# File 'lib/mongoid/changeable.rb', line 176

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:

  • (Hash)

    A Hash of atomic setters.



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/mongoid/changeable.rb', line 125

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.



199
200
201
# File 'lib/mongoid/changeable.rb', line 199

def will_save_change_to_attribute?(attr, **kwargs)
  attribute_changed?(attr, **kwargs)
end