Module: Mongoid::Persistable
Overview
Contains general behavior for persistence operations.
Constant Summary
-
LIST_OPERATIONS =
The atomic operations that deal with arrays or sets in the db.
[ "$addToSet", "$push", "$pull", "$pullAll" ].freeze
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
Instance Attribute Summary
-
#executing_atomically? ⇒ true | false
readonly
private
Internal use only
Internal use only
Are we executing an atomically block on the current document?
Instance Method Summary
-
#atomically(join_context: nil) ⇒ true | false
Execute operations atomically (in a single database call) for everything that would happen inside the block.
-
#fail_due_to_callback!(method)
Raise an error if a callback failed.
-
#fail_due_to_validation!
Raise an error if validation failed.
-
#_mongoid_atomic_context_changed_fields ⇒ Array
private
Internal use only
Internal use only
Return the current atomic context’s changed fields.
-
#_mongoid_pop_atomic_context
private
Internal use only
Internal use only
Pop an atomic context off the stack.
-
#_mongoid_push_atomic_context
private
Internal use only
Internal use only
Push a new atomic context onto the stack.
-
#_mongoid_remove_atomic_context_changes
private
Internal use only
Internal use only
Remove the dirty changes for all fields changed in the current atomic context.
-
#_mongoid_reset_atomic_context_changes!
private
Internal use only
Internal use only
Reset the attributes for all fields changed in the current atomic context.
-
#persist_atomic_operations(operations)
private
Internal use only
Internal use only
Persist the atomic operations.
-
#persist_or_delay_atomic_operation(operation)
private
Internal use only
Internal use only
If we are in an atomically block, add the operations to the delayed group, otherwise persist immediately.
-
#post_process_persist(result, options = {}) ⇒ true
private
Internal use only
Internal use only
Post process the persistence operation.
-
#prepare_atomic_operation ⇒ Object
private
Internal use only
Internal use only
Prepare an atomic persistence operation.
-
#process_atomic_operations(operations) ⇒ Hash
private
Internal use only
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.
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! | Alias for Updatable#update!. |
#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 |
|
Maxable
- Included
#clamp_lower_bound | Alias for Maxable#set_max. |
#set_max |
|
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)
Are we executing an atomically block on the current document?
# File 'lib/mongoid/persistable.rb', line 157
def executing_atomically? !@atomic_updates_to_execute_stack.nil? end
Instance Method Details
#_mongoid_atomic_context_changed_fields ⇒ Array (private)
Return the current atomic context’s changed fields.
# 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)
Pop an atomic context off the stack.
# 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)
Push a new atomic context onto the stack.
# 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)
Remove the dirty changes for all fields changed in the current atomic context.
# 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)
Reset the attributes for all fields changed in the current atomic context.
# 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.
# 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.
#fail_due_to_validation!
Raise an error if validation failed.
# File 'lib/mongoid/persistable.rb', line 131
def fail_due_to_validation! raise Errors::Validations.new(self) end
#persist_atomic_operations(operations) (private)
Persist the atomic operations.
# 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)
If we are in an atomically block, add the operations to the delayed group, otherwise persist immediately.
# 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)
Post process the persistence operation.
# File 'lib/mongoid/persistable.rb', line 174
def post_process_persist(result, = {}) post_persist unless result == false errors.clear unless performing_validations?( ) if in_transaction? Threaded.add_modified_document(_session, self) end true end
#prepare_atomic_operation ⇒ Object
(private)
Prepare an atomic persistence operation. Yields an empty hash to be sent to the update.
# 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)
Process the atomic operations - this handles the common behavior of iterating through each op, getting the aliased field name, and removing appropriate dirty changes.
# 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