class Mongoid::Association::Eager
Base class for eager load preload functions.
Public Class Methods
Instantiate the eager load class.
@example Create the new belongs to eager load preloader.
BelongsTo.new(association, parent_docs)
@param [ Array<Mongoid::Association::Relatable> ] associations
Associations to eager load
@param [ Array<Document> ] docs Documents to preload the associations
@return [ Base ] The eager load preloader
# File lib/mongoid/association/eager.rb, line 19 def initialize(associations, docs) @associations = associations @docs = docs @grouped_docs = {} end
Public Instance Methods
Run the preloader.
@example Preload the associations into the documents.
loader.run
@return [ Array ] The list of documents given.
# File lib/mongoid/association/eager.rb, line 31 def run @loaded = [] while shift_association preload @loaded << @docs.collect { |d| d.send(@association.name) if d.respond_to?(@association.name) } end @loaded.flatten end
Protected Instance Methods
Retrieves the documents referenced by the association, and yields each one sequentially to the provided block. If the association is not polymorphic, all documents are retrieved in a single query. If the association is polymorphic, one query is issued per association target class.
# File lib/mongoid/association/eager.rb, line 57 def each_loaded_document(&block) each_loaded_document_of_class(@association.klass, keys_from_docs, &block) end
Return the key to group the current documents.
This method should be implemented in the subclass
@example Return the key for group
loader.group_by_key
@return [ Symbol ] Key to group by the current documents.
# File lib/mongoid/association/eager.rb, line 132 def group_by_key raise NotImplementedError end
Return a hash with the current documents grouped by key.
Documents that do not have a value for the association being loaded are not returned.
@example Return a hash with the current documents grouped by key.
loader.grouped_docs
@return [ Hash ] hash with grouped documents.
# File lib/mongoid/association/eager.rb, line 103 def grouped_docs @grouped_docs[@association.name] ||= @docs.group_by do |doc| doc.send(group_by_key) if doc.respond_to?(group_by_key) end.reject do |k, v| k.nil? end end
Group the documents and return the keys.
This method omits nil keys (i.e. keys from documents that do not have a value for the association being loaded).
@example
loader.keys_from_docs
@return [ Array ] keys, ids
# File lib/mongoid/association/eager.rb, line 120 def keys_from_docs grouped_docs.keys end
Preload the current association.
This method should be implemented in the subclass
@example Preload the current association into the documents.
loader.preload
# File lib/mongoid/association/eager.rb, line 48 def preload raise NotImplementedError end
Set the pre-loaded document into its parent.
@example Set docs into parent with pk = “foo”
loader.set_on_parent("foo", docs)
@param [ ObjectId ] id parent`s id @param [ Document
| Array ] element to push into the parent
# File lib/mongoid/association/eager.rb, line 88 def set_on_parent(id, element) grouped_docs[id].each do |d| set_relation(d, element) end end
Set the pre-loaded document into its parent.
@example Set docs into parent using the current association name.
loader.set_relation(doc, docs)
@param [ Document
] doc The object to set the association on @param [ Document
| Array ] element to set into the parent
# File lib/mongoid/association/eager.rb, line 143 def set_relation(doc, element) doc.set_relation(@association.name, element) unless doc.blank? end
Private Instance Methods
Retrieves the documents of the specified class, that have the foreign key included in the specified list of keys.
When the documents are retrieved, the set of inclusions applied is the set of inclusions applied to the host document minus the association that is being eagerly loaded.
# File lib/mongoid/association/eager.rb, line 67 def each_loaded_document_of_class(cls, keys) # Note: keys should not include nil elements. # Upstream code is responsible for eliminating nils from keys. return cls.none if keys.empty? criteria = cls.criteria criteria = criteria.apply_scope(@association.scope) criteria = criteria.any_in(key => keys) criteria.inclusions = criteria.inclusions - [@association] criteria.each do |doc| yield doc end end
Shift the current association metadata
@example Shift the current association.
loader.shift_association
@return [ Mongoid::Association::Relatable
] The association object.
# File lib/mongoid/association/eager.rb, line 155 def shift_association @association = @associations.shift end