Class: Mongoid::Association::EagerLoad::DiscriminatedInclusion Private
| Relationships & Source Files | |
| Super Chains via Extension / Inclusion / Inheritance | |
|
Class Chain:
self,
Inclusion
|
|
|
Instance Chain:
self,
Inclusion
|
|
| Inherits: |
Mongoid::Association::EagerLoad::Inclusion
|
| Defined in: | lib/mongoid/association/eager_load/discriminated_inclusion.rb |
Overview
Loads an inclusion that more than one subclass defines under the same name but pointing at different targets. A single $lookup can't serve them: they would all write to the same field and overwrite one another. So each subclass's inclusion is contributed into its own temporary field, carrying its own nested children, and a $set then routes every document to the field for its own type, by the discriminator.
For Machine.eager_load(:widgets), where Lathe#widgets => Cog and Press#widgets => Belt, it emits:
{ '$lookup' => { 'from' => 'cogs', ..., 'as' => '__eager_load_widgets_Lathe' } },
{ '$lookup' => { 'from' => 'belts', ..., 'as' => '__eager_load_widgets_Press' } },
{ '$set' => {
'widgets' => { '$switch' => { 'branches' => [ # route each document to its
{ 'case' => { '$eq' => [ '$_type', 'Lathe' ] }, 'then' => '$__eager_load_widgets_Lathe' }, # own type's matches
{ 'case' => { '$eq' => [ '$_type', 'Press' ] }, 'then' => '$__eager_load_widgets_Press' }
], 'default' => [] } }
} },
{ '$unset' => [ '__eager_load_widgets_Lathe', '__eager_load_widgets_Press' ] }
Class Method Summary
- .new(nodes) ⇒ DiscriminatedInclusion constructor Internal use only
Instance Method Summary
-
#contribute(destination, _chain)
Internal use only
Append each subclass's lookup (into its own temporary field), the routing $set, and the cleanup $unset.
-
#contribute_into_temporary(destination, node)
private
Internal use only
Let the node build its own $lookup (with its nested children) and redirect it to write into a temporary field instead of the shared association name.
- #discriminator_key private Internal use only
- #name private Internal use only
- #owner(node) private Internal use only
-
#route_by_type(fields)
private
Internal use only
The $set that fills the association on each document from the temporary field matching its own type.
- #temporary_field(node) private Internal use only
Inclusion - Inherited
| #contribute | Add this inclusion's stages to the destination. |
Constructor Details
.new(nodes) ⇒ DiscriminatedInclusion
# File 'lib/mongoid/association/eager_load/discriminated_inclusion.rb', line 30
def initialize(nodes) super() @nodes = nodes end
Instance Method Details
#contribute(destination, _chain)
Append each subclass's lookup (into its own temporary field), the routing $set, and the cleanup $unset.
# File 'lib/mongoid/association/eager_load/discriminated_inclusion.rb', line 39
def contribute(destination, _chain) fields = @nodes.map { |node| [ node, contribute_into_temporary(destination, node) ] } destination << route_by_type(fields) destination << { '$unset' => fields.map { |_node, field| field } } end
#contribute_into_temporary(destination, node) (private)
Let the node build its own $lookup (with its nested children) and redirect it to write into a temporary field instead of the shared association name.
# File 'lib/mongoid/association/eager_load/discriminated_inclusion.rb', line 49
def contribute_into_temporary(destination, node) field = temporary_field(node) captured = [] node.contribute(captured, []) captured.first['$lookup']['as'] = field destination.concat(captured) field end
#discriminator_key (private)
[ GitHub ]# File 'lib/mongoid/association/eager_load/discriminated_inclusion.rb', line 82
def discriminator_key owner(@nodes.first).discriminator_key end
#name (private)
[ GitHub ]# File 'lib/mongoid/association/eager_load/discriminated_inclusion.rb', line 78
def name @nodes.first.association.name.to_s end
#owner(node) (private)
[ GitHub ]# File 'lib/mongoid/association/eager_load/discriminated_inclusion.rb', line 74
def owner(node) node.association.inverse_class end
#route_by_type(fields) (private)
The $set that fills the association on each document from the temporary field matching its own type.
# File 'lib/mongoid/association/eager_load/discriminated_inclusion.rb', line 64
def route_by_type(fields) branches = fields.map do |node, field| { 'case' => { '$eq' => [ "$#{discriminator_key}", owner(node).discriminator_value ] }, 'then' => "$#{field}" } end { '$set' => { name => { '$switch' => { 'branches' => branches, 'default' => [] } } } } end