module Mongoid::Touchable::InstanceMethods
Used to provide mixin functionality.
@todo Refactor using ActiveSupport::Concern
Public Instance Methods
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
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
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
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
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 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
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 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