123456789_123456789_123456789_123456789_123456789_

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

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

[ GitHub ]

  
# 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.

Parameters:

Returns:

  • (InclusionTree)

    The tree.

[ GitHub ]

  
# 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.

Parameters:

  • destination (Array<Hash>)

    The pipeline the stages are appended to.

[ GitHub ]

  
# File 'lib/mongoid/association/eager_load/inclusion_tree.rb', line 45

def contribute_to(destination)
  roots.each { |root| root.contribute(destination, []) }
end

#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.

[ GitHub ]

  
# 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).

[ GitHub ]

  
# 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.

[ GitHub ]

  
# 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.

[ GitHub ]

  
# 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