Class: Mongoid::Association::EagerLoad::InclusionTree Private
| Relationships & Source Files | |
| Inherits: | Object |
| Defined in: | lib/mongoid/association/eager_load/inclusion_tree.rb |
Overview
The tree of nested inclusions an eager load asks to load. Built from the criteria's inclusions, it contributes each root node's stages to the pipeline, with each node already carrying its own children.
Each root branch is built from its own copy of the inclusions, and an inclusion is removed as it is placed, so it lands once per branch even if more than one parent in that branch points at it, and a circular chain of inclusions can't loop forever.
Class Method Summary
-
.from(inclusions, pipeline) ⇒ InclusionTree
Internal use only
Builds the tree for the criteria's inclusions.
- .new(inclusions, pipeline, by_name) ⇒ InclusionTree constructor Internal use only
Instance Method Summary
-
#contribute_to(destination)
Internal use only
Contribute each root inclusion's stages to the pipeline.
- #node(association, available) private Internal use only
-
#roots
private
Internal use only
A name that more than one subclass defines (with different targets) can't share one $lookup field, so its nodes -- each carrying its own children -- are grouped and routed by the discriminator instead of becoming separate, overwriting roots.
-
#same_hierarchy?(one, other) ⇒ Boolean
private
Internal use only
Whether two classes belong to the same inheritance chain (one is the other, an ancestor of it, or a descendant of it).
-
#take_children(association, available)
private
Internal use only
The still-available inclusions parented to
association, removed as they are taken so each lands once on this branch. -
#top_level
private
Internal use only
The inclusions that no other inclusion is the parent of.
Constructor Details
.new(inclusions, pipeline, by_name) ⇒ InclusionTree
# File 'lib/mongoid/association/eager_load/inclusion_tree.rb', line 34
def initialize(inclusions, pipeline, by_name) @inclusions = inclusions @pipeline = pipeline @by_name = by_name end
Class Method Details
.from(inclusions, pipeline) ⇒ InclusionTree
Builds the tree for the criteria's inclusions.
# File 'lib/mongoid/association/eager_load/inclusion_tree.rb', line 27
def from(inclusions, pipeline) new(inclusions, pipeline, inclusions.to_h { |association| [ association.name, association ] }) end
Instance Method Details
#contribute_to(destination)
Contribute each root inclusion's stages to the pipeline. Each root carries its own children, so the whole tree is appended by recursion from the roots downward.
#node(association, available) (private)
[ GitHub ]# File 'lib/mongoid/association/eager_load/inclusion_tree.rb', line 69
def node(association, available) children = take_children(association, available).map { |child| node(child, available) } AssociationInclusion.for(association, @pipeline, children) end
#roots (private)
A name that more than one subclass defines (with different targets) can't share one $lookup field, so its nodes -- each carrying its own children -- are grouped and routed by the discriminator instead of becoming separate, overwriting roots.
# File 'lib/mongoid/association/eager_load/inclusion_tree.rb', line 55
def roots top_level.group_by(&:name).map do |_name, associations| nodes = associations.map { |association| node(association, @inclusions.dup) } nodes.one? ? nodes.first : DiscriminatedInclusion.new(nodes) end end
#same_hierarchy?(one, other) ⇒ Boolean (private)
Whether two classes belong to the same inheritance chain (one is the other, an ancestor of it, or a descendant of it).
# File 'lib/mongoid/association/eager_load/inclusion_tree.rb', line 90
def same_hierarchy?(one, other) one <= other || other <= one end
#take_children(association, available) (private)
The still-available inclusions parented to association, removed as they
are taken so each lands once on this branch. A child belongs here when it
names this association as its parent and its owner shares the target's
class hierarchy, which tells apart children of two unrelated subclasses
that share an association name.
# File 'lib/mongoid/association/eager_load/inclusion_tree.rb', line 79
def take_children(association, available) children = available.select do |candidate| candidate.parent_inclusions.include?(association.name) && same_hierarchy?(association.klass, candidate.inverse_class) end available.reject! { |candidate| children.include?(candidate) } children end
#top_level (private)
The inclusions that no other inclusion is the parent of.
# File 'lib/mongoid/association/eager_load/inclusion_tree.rb', line 63
def top_level @inclusions.reject do |association| association.parent_inclusions.any? { |name| @by_name.key?(name) } end end