-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'remotes/origin/master' into docs-full-n…
…amespaces
- Loading branch information
Showing
27 changed files
with
863 additions
and
246 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
# frozen_string_literal: true | ||
|
||
module Mongoid | ||
module Association | ||
|
||
# Base class for eager load preload functions. | ||
class Eager | ||
# 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 | ||
def initialize(associations, docs) | ||
@associations = associations | ||
@docs = docs | ||
@grouped_docs = {} | ||
end | ||
|
||
# Run the preloader. | ||
# | ||
# @example Preload the associations into the documents. | ||
# loader.run | ||
# | ||
# @return [ Array ] The list of documents given. | ||
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 | ||
|
||
# Preload the current association. | ||
# | ||
# This method should be implemented in the subclass | ||
# | ||
# @example Preload the current association into the documents. | ||
# loader.preload | ||
def preload | ||
raise NotImplementedError | ||
end | ||
|
||
# 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. | ||
def each_loaded_document(&block) | ||
each_loaded_document_of_class(@association.klass, keys_from_docs, &block) | ||
end | ||
|
||
# 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. | ||
private 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 | ||
|
||
# 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 | ||
def set_on_parent(id, element) | ||
grouped_docs[id].each do |d| | ||
set_relation(d, element) | ||
end | ||
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. | ||
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 | ||
def keys_from_docs | ||
grouped_docs.keys | ||
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. | ||
def group_by_key | ||
raise NotImplementedError | ||
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 | ||
def set_relation(doc, element) | ||
doc.set_relation(@association.name, element) unless doc.blank? | ||
end | ||
|
||
private | ||
|
||
# Shift the current association metadata | ||
# | ||
# @example Shift the current association. | ||
# loader.shift_association | ||
# | ||
# @return [ Mongoid::Association::Relatable ] The association object. | ||
def shift_association | ||
@association = @associations.shift | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'mongoid/association/embedded/cyclic' | ||
require 'mongoid/association/embedded/eager' | ||
require 'mongoid/association/embedded/embedded_in' | ||
require 'mongoid/association/embedded/embeds_many' | ||
require 'mongoid/association/embedded/embeds_one' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# frozen_string_literal: true | ||
|
||
module Mongoid | ||
module Association | ||
module Embedded | ||
|
||
# Eager class for embedded associations (embedded_in, embeds_many, | ||
# embeds_one). | ||
class Eager < Association::Eager | ||
|
||
private | ||
|
||
# Embedded associations have no preload phase, since the embedded | ||
# documents are loaded with the parent document. This method is | ||
# implemented as a no-op to represent that. | ||
def preload | ||
end | ||
end | ||
|
||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.