Class: Mongoid::Contextual::Memory
| Relationships & Source Files | |
| Super Chains via Extension / Inclusion / Inheritance | |
| Instance Chain: 
          self,
           ::Mongoid::Positional,Queryable,::Mongoid::Association::EagerLoadable,Aggregable::Memory,
          Enumerable | |
| Inherits: | Object | 
| Defined in: | lib/mongoid/contextual/memory.rb | 
Overview
Context object used for performing bulk query and persistence operations on documents which have been loaded into application memory. The method interface of this class is consistent with Mongoid::Contextual::Mongo.
Class Method Summary
- 
    
      .new(criteria)  ⇒ Memory 
    
    constructor
    Create the new in memory context. 
Instance Attribute Summary
- #documents readonly
- #matching The in memory documents that match the selector.(The in memory documents that match the selector.) readonly
- #path readonly
- #path The atomic path.(The atomic path.) readonly
- #root readonly
- #root The root document.(The root document.) readonly
- #selector readonly
- #selector The root document selector.(The root document selector.) readonly
- 
    
      #limiting  ⇒ Integer 
    
    rw
    private
    Internal use only
    Internal use only
    Get the limiting value. 
- 
    
      #limiting=(value)  ⇒ Integer 
    
    rw
    private
    Internal use only
    Internal use only
    ::Setthe limiting value.
- 
    
      #skipping  ⇒ Integer 
    
    rw
    private
    Internal use only
    Internal use only
    Get the skipping value. 
- 
    
      #skipping=(value)  ⇒ Integer 
    
    rw
    private
    Internal use only
    Internal use only
    ::Setthe skipping value.
Queryable - Included
| #blank? | Is the enumerable of matching documents empty? | 
| #collection, #collection The collection to query against., #criteria, #criteria The criteria for the context., | |
| #empty? | Alias for Queryable#blank?. | 
| #klass, #klass The klass for the criteria. | |
::Mongoid::Association::EagerLoadable - Included
| #eager_loadable? | Indicates whether the criteria has association inclusions which should be eager loaded. | 
Instance Method Summary
- 
    
      #==(other)  ⇒ true | false 
    
    Check if the context is equal to the other object. 
- 
    
      #delete  ⇒ nil 
      (also: #delete_all)
    
    Delete all documents in the database that match the selector. 
- 
    
      #delete_all  
    
    Alias for #delete. 
- 
    
      #destroy  ⇒ nil 
      (also: #destroy_all)
    
    Destroy all documents in the database that match the selector. 
- 
    
      #destroy_all  
    
    Alias for #destroy. 
- 
    
      #distinct(field)  ⇒ Array<Object> 
    
    Get the distinct values in the db for the provided field. 
- 
    
      #each  ⇒ Enumerator 
    
    Iterate over the context. 
- 
    
      #exists?(id_or_conditions = :none)  ⇒ true | false 
    
    Do any documents exist for the context. 
- 
    
      #fifth  ⇒ Document 
    
    Get the fifth document in the database for the criteria’s selector. 
- 
    
      #fifth!  ⇒ Document 
    
    Get the fifth document in the database for the criteria’s selector or raise an error if none is found. 
- 
    
      #find_first(limit = nil)  
    
    Alias for #first. 
- 
    
      #first(limit = nil)  ⇒ Document 
      (also: #one, #find_first)
    
    Get the first document in the database for the criteria’s selector. 
- 
    
      #first!  ⇒ Document 
    
    Get the first document in the database for the criteria’s selector or raise an error if none is found. 
- 
    
      #fourth  ⇒ Document 
    
    Get the fourth document in the database for the criteria’s selector. 
- 
    
      #fourth!  ⇒ Document 
    
    Get the fourth document in the database for the criteria’s selector or raise an error if none is found. 
- 
    
      #inc(incs)  ⇒ Enumerator 
    
    Increment a value on all documents. 
- 
    
      #last(limit = nil)  ⇒ Document 
    
    Get the last document in the database for the criteria’s selector. 
- 
    
      #last!  ⇒ Document 
    
    Get the last document in the database for the criteria’s selector or raise an error if none is found. 
- 
    
      #length  ⇒ Integer 
      (also: #size)
    
    Get the length of matching documents in the context. 
- 
    
      #limit(value)  ⇒ Memory 
    
    Limits the number of documents that are returned. 
- 
    
      #one(limit = nil)  
    
    Alias for #first. 
- 
    
      #pick(*fields)  ⇒ Object | Array<Object> 
    
    Pick the field values in memory. 
- 
    
      #pluck(*fields)  ⇒ Array<Object> | Array<Array<Object>> 
    
    Pluck the field values in memory. 
- 
    
      #second  ⇒ Document 
    
    Get the second document in the database for the criteria’s selector. 
- 
    
      #second!  ⇒ Document 
    
    Get the second document in the database for the criteria’s selector or raise an error if none is found. 
- 
    
      #second_to_last  ⇒ Document 
    
    Get the second to last document in the database for the criteria’s selector. 
- 
    
      #second_to_last!  ⇒ Document 
    
    Get the second to last document in the database for the criteria’s selector or raise an error if none is found. 
- 
    
      #size  
    
    Alias for #length. 
- 
    
      #skip(value)  ⇒ Memory 
    
    Skips the provided number of documents. 
- 
    
      #sort(values)  ⇒ Memory 
    
    Sorts the documents by the provided spec. 
- 
    
      #take(limit = nil)  ⇒ Document 
    
    Take the given number of documents from the database. 
- 
    
      #take!  ⇒ Document 
    
    Take the given number of documents from the database or raise an error if none are found. 
- 
    
      #tally(field)  ⇒ Hash 
    
    Tally the field values in memory. 
- 
    
      #third  ⇒ Document 
    
    Get the third document in the database for the criteria’s selector. 
- 
    
      #third!  ⇒ Document 
    
    Get the third document in the database for the criteria’s selector or raise an error if none is found. 
- 
    
      #third_to_last  ⇒ Document 
    
    Get the third to last document in the database for the criteria’s selector. 
- 
    
      #third_to_last!  ⇒ Document 
    
    Get the third to last document in the database for the criteria’s selector or raise an error if none is found. 
- 
    
      #update(attributes = nil)  ⇒ nil | false 
    
    Update the first matching document atomically. 
- 
    
      #update_all(attributes = nil)  ⇒ nil | false 
    
    Update all the matching documents atomically. 
- #_session private
- 
    
      #apply_options  ⇒ Memory 
    
    private
    Internal use only
    Internal use only
    Apply criteria options. 
- 
    
      #apply_sorting  
    
    private
    Map the sort symbols to the correct MongoDB values. 
- 
    
      #compare(a, b)  ⇒ Integer 
    
    private
    Internal use only
    Internal use only
    Compare two values, handling the cases when either value is nil. 
- 
    
      #compare_operand(value)  ⇒ Integer | Object 
    
    private
    Get the operand value to be used in comparison. 
- 
    
      #documents_for_iteration  ⇒ Array<Document> 
    
    private
    Internal use only
    Internal use only
    Get the documents the context should iterate. 
- 
    
      #in_place_sort(values)  
    
    private
    Sort the documents in place. 
- 
    
      #pluck_from_doc(doc, *fields)  ⇒ Object | Array<Object> 
    
    private
    Pluck the field values from the given document. 
- 
    
      #prepare_remove(doc)  
    
    private
    Internal use only
    Internal use only
    Prepare the document for batch removal. 
- #raise_document_not_found_error private
- 
    
      #retrieve_value_at_path(document, field_path)  ⇒ Object | nil 
    
    private
    Retrieve the value for the current document at the given field path. 
- 
    
      #update_documents(attributes, docs)  
    
    private
    Internal use only
    Internal use only
    Update the provided documents with the attributes. 
::Mongoid::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 | |
::Mongoid::Association::EagerLoadable - Included
| #eager_load | Load the associations for the given documents. | 
| #preload | Load the associations for the given documents. | 
Aggregable::Memory - Included
| #aggregates | Get all the aggregate values for the provided field. | 
| #avg | Get the average value of the provided field. | 
| #max | Get the max value of the provided field. | 
| #min | Get the min value of the provided field. | 
| #sum | Get the sum value of the provided field. | 
| #aggregate_by | Aggregate by the provided field and method. | 
Constructor Details
    .new(criteria)  ⇒ Memory 
  
Create the new in memory context.
# File 'lib/mongoid/contextual/memory.rb', line 173
def initialize(criteria) @criteria, @klass = criteria, criteria.klass @documents = criteria.documents.select do |doc| @root ||= doc._root @collection ||= root.collection doc._matches?(criteria.selector) end apply_sorting end
Instance Attribute Details
#documents (readonly)
[ GitHub ]#limiting ⇒ Integer (rw, private)
Get the limiting value.
# File 'lib/mongoid/contextual/memory.rb', line 566
def limiting defined?(@limiting) ? @limiting : nil end
#limiting=(value) ⇒ Integer (rw, private)
::Set the limiting value.
# File 'lib/mongoid/contextual/memory.rb', line 579
def limiting=(value) @limiting = value end
#matching The in memory documents that match the selector.(The in memory documents that match the selector.) (readonly)
[ GitHub ]#path (readonly)
[ GitHub ]#path The atomic path.(The atomic path.) (readonly)
[ GitHub ]#root (readonly)
[ GitHub ]#root The root document.(The root document.) (readonly)
[ GitHub ]#selector (readonly)
[ GitHub ]#selector The root document selector.(The root document selector.) (readonly)
[ GitHub ]#skipping ⇒ Integer (rw, private)
Get the skipping value.
# File 'lib/mongoid/contextual/memory.rb', line 590
def skipping defined?(@skipping) ? @skipping : nil end
#skipping=(value) ⇒ Integer (rw, private)
::Set the skipping value.
# File 'lib/mongoid/contextual/memory.rb', line 603
def skipping=(value) @skipping = value end
Instance Method Details
    #==(other)  ⇒ true | false 
  
Check if the context is equal to the other object.
# File 'lib/mongoid/contextual/memory.rb', line 35
def ==(other) return false unless other.respond_to?(:entries) entries == other.entries end
#_session (private)
[ GitHub ]# File 'lib/mongoid/contextual/memory.rb', line 682
def _session @criteria.send(:_session) end
    #apply_options  ⇒ Memory  (private)
  
  Apply criteria options.
#apply_sorting (private)
Map the sort symbols to the correct MongoDB values.
# File 'lib/mongoid/contextual/memory.rb', line 624
def apply_sorting if spec = criteria.[:sort] in_place_sort(spec) end end
#compare(a, b) ⇒ Integer (private)
Compare two values, handling the cases when either value is nil.
# File 'lib/mongoid/contextual/memory.rb', line 642
def compare(a, b) return 0 if a.nil? && b.nil? return 1 if a.nil? return -1 if b.nil? compare_operand(a) <=> compare_operand(b) end
    #compare_operand(value)  ⇒ Integer | Object  (private)
  
Get the operand value to be used in comparison. Adds capability to sort boolean values.
# File 'lib/mongoid/contextual/memory.rb', line 695
def compare_operand(value) case value when TrueClass then 1 when FalseClass then 0 else value end end
    #delete  ⇒ nil 
    Also known as: #delete_all
  
Delete all documents in the database that match the selector.
# File 'lib/mongoid/contextual/memory.rb', line 46
def delete deleted = count removed = map do |doc| prepare_remove(doc) doc.send(:as_attributes) end unless removed.empty? collection.find(selector).update_one( positionally(selector, "$pullAll" => { path => removed }), session: _session ) end deleted end
#delete_all
Alias for #delete.
# File 'lib/mongoid/contextual/memory.rb', line 60
alias :delete_all :delete
    #destroy  ⇒ nil 
    Also known as: #destroy_all
  
Destroy all documents in the database that match the selector.
#destroy_all
Alias for #destroy.
# File 'lib/mongoid/contextual/memory.rb', line 76
alias :destroy_all :destroy
    #distinct(field)  ⇒ Array<Object> 
  
Get the distinct values in the db for the provided field.
# File 'lib/mongoid/contextual/memory.rb', line 86
def distinct(field) pluck(field).uniq end
#documents_for_iteration ⇒ Array<Document> (private)
Get the documents the context should iterate. This follows 3 rules:
    #each  ⇒ Enumerator 
  
Iterate over the context. If provided a block, yield to a ::Mongoid document for each, otherwise return an enum.
# File 'lib/mongoid/contextual/memory.rb', line 99
def each if block_given? documents_for_iteration.each do |doc| yield(doc) end self else to_enum end end
    #exists?(id_or_conditions = :none)  ⇒ true | false 
  
Do any documents exist for the context.
#fifth ⇒ Document
Get the fifth document in the database for the criteria’s selector.
#fifth! ⇒ Document
Get the fifth document in the database for the criteria’s selector or raise an error if none is found.
# File 'lib/mongoid/contextual/memory.rb', line 468
def fifth! fifth || raise_document_not_found_error end
#find_first(limit = nil)
Alias for #first.
# File 'lib/mongoid/contextual/memory.rb', line 151
alias :find_first :first
#first(limit = nil) ⇒ Document Also known as: #one, #find_first
Get the first document in the database for the criteria’s selector.
#first! ⇒ Document
Get the first document in the database for the criteria’s selector or raise an error if none is found.
# File 'lib/mongoid/contextual/memory.rb', line 163
def first! first || raise_document_not_found_error end
#fourth ⇒ Document
Get the fourth document in the database for the criteria’s selector.
#fourth! ⇒ Document
Get the fourth document in the database for the criteria’s selector or raise an error if none is found.
# File 'lib/mongoid/contextual/memory.rb', line 444
def fourth! fourth || raise_document_not_found_error end
#in_place_sort(values) (private)
Sort the documents in place.
    #inc(incs)  ⇒ Enumerator 
  
Increment a value on all documents.
# File 'lib/mongoid/contextual/memory.rb', line 192
def inc(incs) each do |document| document.inc(incs) end end
#last(limit = nil) ⇒ Document
Get the last document in the database for the criteria’s selector.
#last! ⇒ Document
Get the last document in the database for the criteria’s selector or raise an error if none is found.
# File 'lib/mongoid/contextual/memory.rb', line 224
def last! last || raise_document_not_found_error end
#length ⇒ Integer Also known as: #size
Get the length of matching documents in the context.
# File 'lib/mongoid/contextual/memory.rb', line 234
def length documents.length end
    #limit(value)  ⇒ Memory 
  
Limits the number of documents that are returned.
# File 'lib/mongoid/contextual/memory.rb', line 247
def limit(value) self.limiting = value self end
#one(limit = nil)
Alias for #first.
# File 'lib/mongoid/contextual/memory.rb', line 150
alias :one :first
    #pick(*fields)  ⇒ Object | Array<Object> 
  
Pick the field values in memory.
# File 'lib/mongoid/contextual/memory.rb', line 274
def pick(*fields) if doc = documents.first pluck_from_doc(doc, *fields) end end
    #pluck(*fields)  ⇒ Array<Object> | Array<Array<Object>> 
  
Pluck the field values in memory.
# File 'lib/mongoid/contextual/memory.rb', line 260
def pluck(*fields) documents.map do |doc| pluck_from_doc(doc, *fields) end end
    #pluck_from_doc(doc, *fields)  ⇒ Object | Array<Object>  (private)
  
Pluck the field values from the given document.
# File 'lib/mongoid/contextual/memory.rb', line 766
def pluck_from_doc(doc, *fields) if fields.length == 1 retrieve_value_at_path(doc, fields.first) else fields.map do |field| retrieve_value_at_path(doc, field) end end end
#prepare_remove(doc) (private)
Prepare the document for batch removal.
#raise_document_not_found_error (private)
# File 'lib/mongoid/contextual/memory.rb', line 776
def raise_document_not_found_error raise Errors::DocumentNotFound.new(klass, nil, nil) end
    #retrieve_value_at_path(document, field_path)  ⇒ Object | nil  (private)
  
Retrieve the value for the current document at the given field path.
For example, if I have the following models:
User has_many Accounts
address is a hash on Account
u = User.new(accounts: [ Account.new(address: { street: "W 50th" }) ])
retrieve_value_at_path(u, "user.accounts.address.street")
# => [ "W 50th" ]Note that the result is in an array since accounts is an array. If it was nested in two arrays the result would be in a 2D array.
# File 'lib/mongoid/contextual/memory.rb', line 723
def retrieve_value_at_path(document, field_path) return if field_path.blank? || !document segment, remaining = field_path.to_s.split('.', 2) curr = if document.is_a?(Document) # Retrieves field for segment to check localization. Only does one # iteration since there's no dots res = if remaining field = document.class.traverse_association_tree(segment) # If this is a localized field, and there are remaining, get the # _translations hash so that we can get the specified translation in # the remaining if field&.localized? document.send("#{segment}_translations") end end meth = klass.aliased_associations[segment] || segment res.nil? ? document.try(meth) : res elsif document.is_a?(Hash) # TODO: Remove the indifferent access when implementing MONGOID-5410. document.key?(segment.to_s) ? document[segment.to_s] : document[segment.to_sym] else nil end return curr unless remaining if curr.is_a?(Array) # compact is used for consistency with server behavior. curr.map { |d| retrieve_value_at_path(d, remaining) }.compact else retrieve_value_at_path(curr, remaining) end end
#second ⇒ Document
Get the second document in the database for the criteria’s selector.
#second! ⇒ Document
Get the second document in the database for the criteria’s selector or raise an error if none is found.
# File 'lib/mongoid/contextual/memory.rb', line 396
def second! second || raise_document_not_found_error end
#second_to_last ⇒ Document
Get the second to last document in the database for the criteria’s selector.
#second_to_last! ⇒ Document
Get the second to last document in the database for the criteria’s selector or raise an error if none is found.
# File 'lib/mongoid/contextual/memory.rb', line 492
def second_to_last! second_to_last || raise_document_not_found_error end
#size
Alias for #length.
# File 'lib/mongoid/contextual/memory.rb', line 237
alias :size :length
    #skip(value)  ⇒ Memory 
  
Skips the provided number of documents.
# File 'lib/mongoid/contextual/memory.rb', line 334
def skip(value) self.skipping = value self end
    #sort(values)  ⇒ Memory 
  
Sorts the documents by the provided spec.
# File 'lib/mongoid/contextual/memory.rb', line 348
def sort(values) in_place_sort(values) and self end
#take(limit = nil) ⇒ Document
Take the given number of documents from the database.
#take! ⇒ Document
Take the given number of documents from the database or raise an error if none are found.
# File 'lib/mongoid/contextual/memory.rb', line 322
def take! take || raise_document_not_found_error end
#tally(field) ⇒ Hash
Tally the field values in memory.
# File 'lib/mongoid/contextual/memory.rb', line 288
def tally(field) return documents.each_with_object({}) do |d, acc| v = retrieve_value_at_path(d, field) acc[v] ||= 0 acc[v] += 1 end end
#third ⇒ Document
Get the third document in the database for the criteria’s selector.
#third! ⇒ Document
Get the third document in the database for the criteria’s selector or raise an error if none is found.
# File 'lib/mongoid/contextual/memory.rb', line 420
def third! third || raise_document_not_found_error end
#third_to_last ⇒ Document
Get the third to last document in the database for the criteria’s selector.
#third_to_last! ⇒ Document
Get the third to last document in the database for the criteria’s selector or raise an error if none is found.
# File 'lib/mongoid/contextual/memory.rb', line 516
def third_to_last! third_to_last || raise_document_not_found_error end
    #update(attributes = nil)  ⇒ nil | false 
  
Update the first matching document atomically.
# File 'lib/mongoid/contextual/memory.rb', line 360
def update(attributes = nil) update_documents(attributes, [ first ]) end
    #update_all(attributes = nil)  ⇒ nil | false 
  
Update all the matching documents atomically.
# File 'lib/mongoid/contextual/memory.rb', line 372
def update_all(attributes = nil) update_documents(attributes, entries) end
#update_documents(attributes, docs) (private)
Update the provided documents with the attributes.
# File 'lib/mongoid/contextual/memory.rb', line 547
def update_documents(attributes, docs) return false if !attributes || docs.empty? updates = { "$set" => {}} docs.each do |doc| @selector ||= root.atomic_selector doc.write_attributes(attributes) updates["$set"].merge!(doc.atomic_updates["$set"] || {}) doc.move_changes end collection.find(selector).update_one(updates, session: _session) unless updates["$set"].empty? end