module Mongoid::Touchable::InstanceMethods

Used to provide mixin functionality.

@todo Refactor using ActiveSupport::Concern

Public Instance Methods

_clear_touch_updates(field = nil) click to toggle source

Clears changes for the model caused by touch operation.

@param [ Symbol ] field The name of an additional field to update.

@api private

# File lib/mongoid/touchable.rb, line 93
def _clear_touch_updates(field = nil)
  remove_change(:updated_at)
  remove_change(field) if field
  _parent._clear_touch_updates if _touchable_parent?
end
_gather_touch_updates(now, field = nil) click to toggle source

Recursively sets touchable fields on the current document and each of its parents, including the root node. Returns the combined atomic $set operations to be performed on the root document.

@param [ Time ] now The timestamp used for synchronizing the touched time. @param [ Symbol ] field The name of an additional field to update.

@return [ Hash<String, Time> ] The touch operations to perform as an atomic $set.

@api private

# File lib/mongoid/touchable.rb, line 75
def _gather_touch_updates(now, field = nil)
  return if touch_callbacks_suppressed?

  field = database_field_name(field)

  write_attribute(:updated_at, now) if respond_to?("updated_at=")
  write_attribute(field, now) if field.present?

  touches = _extract_touches_from_atomic_sets(field) || {}
  touches.merge!(_parent._gather_touch_updates(now) || {}) if _touchable_parent?
  touches
end
_run_touch_callbacks_from_root() click to toggle source

Recursively runs :touch callbacks for the document and its parents, beginning with the root document and cascading through each successive child document.

@api private

# File lib/mongoid/touchable.rb, line 104
def _run_touch_callbacks_from_root
  return if touch_callbacks_suppressed?
  _parent._run_touch_callbacks_from_root if _touchable_parent?
  run_callbacks(:touch)
end
_touchable_parent?() click to toggle source

Indicates whether the parent exists and is touchable.

@api private

# File lib/mongoid/touchable.rb, line 113
def _touchable_parent?
  _parent && _association&.inverse_association&.touchable?
end
suppress_touch_callbacks() { || ... } click to toggle source

Suppresses the invocation of touch callbacks, for the class that includes this module, for the duration of the block.

@example Suppress touch callbacks on Person documents:

person.suppress_touch_callbacks { ... }

@api private

# File lib/mongoid/touchable.rb, line 22
def suppress_touch_callbacks
  Touchable.suppress_touch_callbacks(self.class.name) { yield }
end
touch(field = nil) click to toggle source

Touch the document, in effect updating its updated_at timestamp and optionally the provided field to the current time. If any belongs_to associations exist with a touch option, they will be updated as well.

@example Update the updated_at timestamp.

document.touch

@example Update the updated_at and provided timestamps.

document.touch(:audited)

@note This will not autobuild associations if those options are set.

@param [ Symbol ] field The name of an additional field to update.

@return [ true/false ] false if document is new_record otherwise true.

# File lib/mongoid/touchable.rb, line 51
def touch(field = nil)
  return false if _root.new_record?

  begin
    touches = _gather_touch_updates(Time.current, field)
    _root.send(:persist_atomic_operations, '$set' => touches) if touches.present?
    _run_touch_callbacks_from_root
  ensure
    _clear_touch_updates(field)
  end

  true
end
touch_callbacks_suppressed?() click to toggle source

Queries whether touch callbacks are being suppressed for the class that includes this module.

@return [ true | false ] Whether touch callbacks are suppressed.

@api private

# File lib/mongoid/touchable.rb, line 32
def touch_callbacks_suppressed?
  Touchable.touch_callbacks_suppressed?(self.class.name)
end

Private Instance Methods

_extract_touches_from_atomic_sets(field = nil) click to toggle source

Extract and remove the atomic updates for the touch operation(s) from the currently enqueued atomic $set operations.

@param [ Symbol ] field The optional field.

@return [ Hash ] The field-value pairs to update atomically.

@api private

# File lib/mongoid/touchable.rb, line 127
def _extract_touches_from_atomic_sets(field = nil)
  updates = atomic_updates['$set']
  return {} unless updates

  touchable_keys = Set['updated_at', 'u_at']
  touchable_keys << field.to_s if field.present?

  updates.keys.each_with_object({}) do |key, touches|
    if touchable_keys.include?(key.split('.').last)
      touches[key] = updates.delete(key)
    end
  end
end