Module: Mongoid::Atomicity
Overview
Durran: Refactor class out into separate objects for each type of update.
This module contains the logic for supporting atomic operations against the database.
Instance Method Summary collapse
-
#_updates ⇒ Hash
Get all the atomic updates that need to happen for the current
Document
.
Instance Method Details
#_updates ⇒ Hash
MongoDB does not allow “conflicting modifications” to be performed in a single operation. Conflicting modifications are detected by the ‘haveConflictingMod’ function in MongoDB. Examination of the code suggests that two modifications (a $set and a $pushAll, for example) conflict if:
(1) the key paths being modified are equal.
(2) one key path is a prefix of the other.
So a $set of ‘addresses.0.street’ will conflict with a $pushAll to ‘addresses’, and we will need to split our update into two pieces. We do not, however, attempt to match MongoDB’s logic exactly. Instead, we assume that two updates conflict if the first component of the two key paths matches.
Get all the atomic updates that need to happen for the current Document
. This includes all changes that need to happen in the entire hierarchy that exists below where the save call was made.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/mongoid/atomicity.rb', line 34 def _updates processed = {} _children.inject({ "$set" => _sets, "$pushAll" => {}, :other => {} }) do |updates, child| changes = child._sets updates["$set"].update(changes) unless changes.empty? processed[child._conflicting_modification_key] = true end if processed.has_key?(child._conflicting_modification_key) target = :other else target = "$pushAll" end child._pushes.each do |attr, val| if updates[target].has_key?(attr) updates[target][attr] << val else updates[target].update({attr => [val]}) end end updates end.delete_if do |key, value| value.empty? end end |