123456789_123456789_123456789_123456789_123456789_

Module: Mongoid::Touchable::InstanceMethods

Relationships & Source Files
Extension / Inclusion / Inheritance Descendants
Included In:
Defined in: lib/mongoid/touchable.rb

Overview

TODO:

Refactor using ActiveSupport::Concern

Used to provide mixin functionality.

Instance Attribute Summary

Instance Method Summary

Instance Attribute Details

#_touchable_parent? ⇒ Boolean (readonly)

Indicates whether the parent exists and is touchable.

[ GitHub ]

  
# File 'lib/mongoid/touchable.rb', line 137

def _touchable_parent?
  _parent && _association&.inverse_association&.touchable?
end

#touch_callbacks_suppressed? ⇒ true | false (readonly)

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

Returns:

  • (true | false) —

    Whether touch callbacks are suppressed.

[ GitHub ]

  
# File 'lib/mongoid/touchable.rb', line 28

def touch_callbacks_suppressed?
  Touchable.touch_callbacks_suppressed?(self.class.name)
end

Instance Method Details

#_clear_touch_updates(field = nil)

Clears changes for the model caused by touch operation.

Parameters:

  • field (Symbol) (defaults to: nil) —

    The name of an additional field to update.

[ GitHub ]

  
# File 'lib/mongoid/touchable.rb', line 89

def _clear_touch_updates(field = nil)
  remove_change(:updated_at)
  remove_change(field) if field
  _parent._clear_touch_updates if _touchable_parent?
end

#_extract_touches_from_atomic_sets(field = nil) ⇒ Hash (private)

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

Parameters:

  • field (Symbol) (defaults to: nil) —

    The optional field.

Returns:

  • (Hash) —

    The field-value pairs to update atomically.

[ GitHub ]

  
# File 'lib/mongoid/touchable.rb', line 151

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|
    touches[key] = updates.delete(key) if touchable_keys.include?(key.split('.').last)
  end
end

#_gather_touch_updates(now, field = nil) ⇒ Hash<String, Time>

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.

Parameters:

  • now (Time) —

    The timestamp used for synchronizing the touched time.

  • field (Symbol) (defaults to: nil) —

    The name of an additional field to update.

Returns:

  • (Hash<String, Time>) —

    The touch operations to perform as an atomic $set.

[ GitHub ]

  
# File 'lib/mongoid/touchable.rb', line 71

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

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

[ GitHub ]

  
# File 'lib/mongoid/touchable.rb', line 100

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_chain_paths(field = nil) ⇒ Array<String>

The root-relative paths that a touch of this document's parent chain writes: the (possibly aliased) updated_at field of each touchable node in the chain, plus this document's custom touch field, if any.

Parameters:

  • field (Symbol, String, nil) (defaults to: nil) —

    The custom touch field.

Returns:

[ GitHub ]

  
# File 'lib/mongoid/touchable.rb', line 116

def _touchable_chain_paths(field = nil)
  field = database_field_name(field) if field

  node = self
  paths = []
  loop do
    if node.respond_to?(:updated_at=)
      paths << node.atomic_attribute_name(node.database_field_name(:updated_at))
    end
    paths << node.atomic_attribute_name(field) if node.equal?(self) && field

    break unless node._touchable_parent?

    node = node._parent
  end
  paths
end

#suppress_touch_callbacks(&block)

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

Examples:

Suppress touch callbacks on Person documents:

person.suppress_touch_callbacks { ... }
[ GitHub ]

  
# File 'lib/mongoid/touchable.rb', line 18

def suppress_touch_callbacks(&block)
  Touchable.suppress_touch_callbacks(self.class.name, &block)
end

#touch(field = nil) ⇒ true/false

Note:

This will not autobuild associations if those options are set.

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.

Examples:

Update the updated_at timestamp.

document.touch

Update the updated_at and provided timestamps.

document.touch(:audited)

Parameters:

  • field (Symbol) (defaults to: nil) —

    The name of an additional field to update.

Returns:

  • (true/false) —

    false if document is new_record otherwise true.

[ GitHub ]

  
# File 'lib/mongoid/touchable.rb', line 47

def touch(field = nil)
  return false if _root.new_record?

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

  true
end