123456789_123456789_123456789_123456789_123456789_

Module: Mongoid::Persistable

Overview

Contains general behavior for persistence operations.

Constant Summary

Class Method Summary

Persistable::Destroyable::ClassMethods - Extended

destroy_all

Delete all documents given the supplied conditions.

Persistable::Deletable::ClassMethods - Extended

delete_all

Delete all documents given the supplied conditions.

Persistable::Creatable::ClassMethods - Extended

create

Create a new document.

create!

Create a new document.

Instance Attribute Summary

Instance Method Summary

Unsettable - Included

#unset

Perform an $unset operation on the provided fields and in the values in the document in memory.

Upsertable - Included

#upsert

Perform an upsert of the document.

#prepare_upsert

Prepare the upsert for execution.

Updatable - Included

#update

Update the document attributes in the database.

#update!

Update the document attributes in the database and raise an error if validation failed.

#update_attribute

Update a single attribute and persist the entire document.

#update_attributes

Alias for Updatable#update.

#update_attributes!
#enforce_immutability_of_id_field!

Checks to see if the _id field has been modified.

#init_atomic_updates

Initialize the atomic updates.

#prepare_update

Prepare the update for execution.

#process_touch_option

If there is a touch option and it is false, this method will call the timeless method so that the updated_at attribute is not updated.

#run_all_callbacks_for_update

Consolidates all the callback invocations into a single place, to avoid cluttering the logic in #prepare_update.

#update_document

Update the document in the database.

Settable - Included

#set

Perform a $set operation on the provided field/value pairs and set the values in the document in memory.

Savable - Included

#save

Save the document - will perform an insert if the document is new, and update if not.

#save!

Save the document - will perform an insert if the document is new, and update if not.

Renamable - Included

#rename

Rename fields from one value to another via $rename.

Pushable - Included

#add_to_set

Add the single values to the arrays only if the value does not already exist in the array.

#push

Push a single value or multiple values onto arrays.

Pullable - Included

#pull

Pull single values from the provided arrays.

#pull_all

Pull multiple values from the provided array fields.

Positional - Included

#positionally

Takes the provided selector and atomic operations and replaces the indexes of the embedded documents with the positional operator when needed.

#process_operations, #process_updates, #replace_index

Poppable - Included

#pop

Pop or shift items from arrays using the $pop operator.

Multipliable - Included

#mul

Multiply the provided fields by the corresponding values.

Minable - Included

#clamp_upper_bound

Alias for Minable#set_min.

#set_min

::Set the given field or fields to the smaller of either it’s current value, or a given value.

Maxable - Included

#clamp_lower_bound

Alias for Maxable#set_max.

#set_max

::Set the given field or fields to the larger of either it’s current value, or a given value.

Logical - Included

#bit

Performs an atomic $bit operation on the field with the provided hash of bitwise ops to execute in order.

Incrementable - Included

#inc

Increment the provided fields by the corresponding values.

Destroyable - Included

#destroy

Remove the document from the database with callbacks.

#destroy!

Remove the document from the database with callbacks.

Deletable - Included

#delete

Remove the document from the database.

#remove

Alias for Deletable#delete.

#atomic_deletes

Get the atomic deletes for the operation.

#delete_as_embedded

Delete the embedded document.

#delete_as_root

Delete the root document.

#notifying_parent?

Are we needing to notify the parent document of the deletion.

#prepare_delete

Prepare the delete operation.

Creatable - Included

#insert

Insert a new document into the database.

#atomic_inserts

Get the atomic insert for embedded documents, either a push or set.

#insert_as_embedded

Insert the embedded document.

#insert_as_root

Insert the root document.

#post_process_insert

Post process an insert, which sets the new record attribute to false and flags all the children as persisted.

#prepare_insert

Prepare the insert for execution.

Instance Attribute Details

#executing_atomically?true | false (readonly, private)

This method is for internal use only.

Are we executing an atomically block on the current document?

Examples:

Are we executing atomically?

document.executing_atomically?

Returns:

  • (true | false)

    If we are current executing atomically.

[ GitHub ]

  
# File 'lib/mongoid/persistable.rb', line 157

def executing_atomically?
  !@atomic_updates_to_execute_stack.nil?
end

Instance Method Details

#_mongoid_atomic_context_changed_fieldsArray (private)

This method is for internal use only.

Return the current atomic context’s changed fields.

Examples:

Return the current atomic context’s changed fields.

document._mongoid_atomic_context_changed_fields

Returns:

  • (Array)

    The changed fields.

[ GitHub ]

  
# File 'lib/mongoid/persistable.rb', line 279

def _mongoid_atomic_context_changed_fields
  @atomic_context.values.flat_map(&:keys)
end

#_mongoid_pop_atomic_context (private)

This method is for internal use only.

Pop an atomic context off the stack.

Examples:

Pop an atomic context off the stack.

document._mongoid_pop_atomic_context
[ GitHub ]

  
# File 'lib/mongoid/persistable.rb', line 265

def _mongoid_pop_atomic_context
  return unless executing_atomically?
  @atomic_updates_to_execute_stack.pop
  @atomic_context = @atomic_updates_to_execute_stack.last
end

#_mongoid_push_atomic_context (private)

This method is for internal use only.

Push a new atomic context onto the stack.

Examples:

Push a new atomic context onto the stack.

document._mongoid_push_atomic_context
[ GitHub ]

  
# File 'lib/mongoid/persistable.rb', line 253

def _mongoid_push_atomic_context
  return unless executing_atomically?
  @atomic_context = {}
  @atomic_updates_to_execute_stack << @atomic_context
end

#_mongoid_remove_atomic_context_changes (private)

This method is for internal use only.

Remove the dirty changes for all fields changed in the current atomic context.

Examples:

Remove the current atomic context’s dirty changes.

document._mongoid_remove_atomic_context_changes
[ GitHub ]

  
# File 'lib/mongoid/persistable.rb', line 230

def _mongoid_remove_atomic_context_changes
  return unless executing_atomically?
  _mongoid_atomic_context_changed_fields.each { |f| remove_change f }
end

#_mongoid_reset_atomic_context_changes! (private)

This method is for internal use only.

Reset the attributes for all fields changed in the current atomic context.

Examples:

Reset the current atomic context’s changed attributes.

document._mongoid_reset_atomic_context_changes!
[ GitHub ]

  
# File 'lib/mongoid/persistable.rb', line 242

def _mongoid_reset_atomic_context_changes!
  return unless executing_atomically?
  _mongoid_atomic_context_changed_fields.each { |f| reset_attribute! f }
end

#atomically(join_context: nil) ⇒ true | false

Execute operations atomically (in a single database call) for everything that would happen inside the block. This method supports nesting further calls to atomically, which will behave according to the options described below.

An option join_context can be given which, when true, will merge the operations declared by the given block with the atomically block wrapping the current invocation for the same document, if one exists. If this block or any other block sharing the same context raises before persisting, then all the operations of that context will not be persisted, and will also be reset in memory.

When join_context is false, the given block of operations will be persisted independently of other contexts. Failures in other contexts will not affect this one, so long as this block was able to run and persist changes.

The default value of join_context is set by the global configuration option join_contexts, whose own default is false.

Examples:

Execute the operations atomically.

document.atomically do
  document.set(name: "Tool").inc(likes: 10)
end

Execute some inner operations atomically, but independently from the outer operations.

document.atomically do
  document.inc likes: 10
  document.atomically join_context: false do
    # The following is persisted to the database independently.
    document.unset :origin
  end
  document.atomically join_context: true do
    # The following is persisted along with the other outer operations.
    document.inc member_count: 3
  end
  document.set name: "Tool"
end

Parameters:

  • join_context (true | false)

    Join the context (i.e. merge declared atomic operations) of the atomically block wrapping this one for the same document, if one exists.

Returns:

  • (true | false)

    If the operation succeeded.

[ GitHub ]

  
# File 'lib/mongoid/persistable.rb', line 94

def atomically(join_context: nil)
  join_context = Mongoid.join_contexts if join_context.nil?
  call_depth = @atomic_depth ||= 0
  has_own_context = call_depth.zero? || !join_context
  @atomic_updates_to_execute_stack ||= []
  _mongoid_push_atomic_context if has_own_context

  if block_given?
    @atomic_depth += 1
    yield(self)
    @atomic_depth -= 1
  end

  if has_own_context
    persist_atomic_operations @atomic_context
    _mongoid_remove_atomic_context_changes
  end

  true
rescue StandardError => e
  _mongoid_reset_atomic_context_changes! if has_own_context
  raise e
ensure
  _mongoid_pop_atomic_context if has_own_context

  if call_depth.zero?
    @atomic_depth = nil
    @atomic_updates_to_execute_stack = nil
  end
end

#fail_due_to_callback!(method)

Raise an error if a callback failed.

Examples:

Raise the callback error.

Person.fail_due_to_callback!(person, :create!)

Parameters:

  • method (Symbol)

    The method being called.

Raises:

[ GitHub ]

  
# File 'lib/mongoid/persistable.rb', line 143

def fail_due_to_callback!(method)
  raise Errors::Callback.new(self.class, method)
end

#fail_due_to_validation!

Raise an error if validation failed.

Examples:

Raise the validation error.

Person.fail_due_to_validation!(person)

Raises:

[ GitHub ]

  
# File 'lib/mongoid/persistable.rb', line 131

def fail_due_to_validation!
  raise Errors::Validations.new(self)
end

#persist_atomic_operations(operations) (private)

This method is for internal use only.

Persist the atomic operations.

Examples:

Persist the atomic operations.

persist_atomic_operations(ops)

Parameters:

  • operations (Hash)

    The atomic operations.

[ GitHub ]

  
# File 'lib/mongoid/persistable.rb', line 311

def persist_atomic_operations(operations)
  if persisted? && operations && !operations.empty?
    selector = atomic_selector
    _root.collection.find(selector).update_one(positionally(selector, operations), session: _session)
  end
end

#persist_or_delay_atomic_operation(operation) (private)

This method is for internal use only.

If we are in an atomically block, add the operations to the delayed group, otherwise persist immediately.

Examples:

Persist immediately or delay the operations.

document.persist_or_delay_atomic_operation(ops)

Parameters:

  • operation (Hash)

    The operation.

[ GitHub ]

  
# File 'lib/mongoid/persistable.rb', line 292

def persist_or_delay_atomic_operation(operation)
  if executing_atomically?
    operation.each do |(name, hash)|
      @atomic_context[name] ||= {}
      @atomic_context[name].merge!(hash)
    end
  else
    persist_atomic_operations(operation)
  end
end

#post_process_persist(result, options = {}) ⇒ true (private)

This method is for internal use only.

Post process the persistence operation.

Examples:

Post process the persistence operation.

document.post_process_persist(true)

Parameters:

  • result (Object)

    The result of the operation.

  • options (Hash) (defaults to: {})

    The options.

Options Hash (options):

  • :validate (true | false)

    Whether or not to validate.

Returns:

  • (true)

    true.

[ GitHub ]

  
# File 'lib/mongoid/persistable.rb', line 174

def post_process_persist(result, options = {})
  post_persist unless result == false
  errors.clear unless performing_validations?(options)
  if in_transaction?
    Threaded.add_modified_document(_session, self)
  end
  true
end

#prepare_atomic_operationObject (private)

This method is for internal use only.

Prepare an atomic persistence operation. Yields an empty hash to be sent to the update.

Examples:

Prepare the atomic operation.

document.prepare_atomic_operation do |coll, selector, opts|
  ...
end

Returns:

  • (Object)

    The result of the operation.

Raises:

[ GitHub ]

  
# File 'lib/mongoid/persistable.rb', line 194

def prepare_atomic_operation
  raise Errors::ReadonlyDocument.new(self.class) if readonly? && !Mongoid.legacy_readonly
  operations = yield({})
  persist_or_delay_atomic_operation(operations)
  self
end

#process_atomic_operations(operations) ⇒ Hash (private)

This method is for internal use only.

Process the atomic operations - this handles the common behavior of iterating through each op, getting the aliased field name, and removing appropriate dirty changes.

Examples:

Process the atomic operations.

document.process_atomic_operations(pulls) do |field, value|
  ...
end

Parameters:

  • operations (Hash)

    The atomic operations.

Returns:

  • (Hash)

    The operations.

[ GitHub ]

  
# File 'lib/mongoid/persistable.rb', line 215

def process_atomic_operations(operations)
  operations.each do |field, value|
    access = database_field_name(field)
    yield(access, value)
    remove_change(access) unless executing_atomically?
  end
end