123456789_123456789_123456789_123456789_123456789_

Module: Mongoid::Pluckable Private

Do not use. This module is for internal use only.
Relationships & Source Files
Extension / Inclusion / Inheritance Descendants
Included In:
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, ActiveSupport::Concern
Defined in: lib/mongoid/pluckable.rb

Overview

Provides shared behavior for any document with “pluck” functionality.

Instance Method Summary

Instance Method Details

#descend(part, current, method_name, field, part_count, is_translation) ⇒ Object (private)

Descend one level in the attribute hash.

Parameters:

  • part (Integer)

    The current part index.

  • current (Hash | Array<Hash>)

    The current level in the attribute hash.

  • method_name (String)

    The method name to descend to.

  • field (Field|nil)

    The field to use for demongoization.

  • is_translation (Boolean)

    Whether the method is an _translations field.

  • part_count (Integer)

    The total number of parts in the field name.

Returns:

  • (Object)

    The value at the next level.

[ GitHub ]

  
# File 'lib/mongoid/pluckable.rb', line 104

def descend(part, current, method_name, field, part_count, is_translation)
  # 1. If curr is an array fetch from all elements in the array.
  # 2. If the field is localized, and is not an _translations field
  #    (_translations fields don't show up in the fields hash).
  #    - If this is the end of the methods, return the translation for
  #      the current locale.
  #    - Otherwise, return the whole translations hash so the next method
  #      can select the language it wants.
  # 3. If the meth is an _translations field, do not demongoize the
  #    value so the full hash is returned.
  # 4. Otherwise, fetch and demongoize the value for the key meth.
  if current.is_a? Array
    res = fetch_and_demongoize(current, method_name, field)
    res.empty? ? nil : res
  elsif !is_translation && field&.localized?
    if part < part_count
      current.try(:fetch, method_name, nil)
    else
      fetch_and_demongoize(current, method_name, field)
    end
  elsif is_translation
    current.try(:fetch, method_name, nil)
  else
    fetch_and_demongoize(current, method_name, field)
  end
end

#extract_value(attrs, field_name, document_class) ⇒ Object (private)

Extracts the value for the given field name from the given attribute hash.

Parameters:

  • attrs (Hash)

    The attributes hash.

  • field_name (String)

    The name of the field to extract.

Returns:

  • (Object)

    The value for the given field name

[ GitHub ]

  
# File 'lib/mongoid/pluckable.rb', line 65

def extract_value(attrs, field_name, document_class)
  i = 1
  num_meths = field_name.count('.') + 1
  curr = attrs.dup

  document_class.traverse_association_tree(field_name) do |meth, obj, is_field|
    field = obj if is_field

    # use the correct document class to check for localized fields on
    # embedded documents.
    document_class = obj.klass if obj.respond_to?(:klass)

    is_translation = false
    # If no association or field was found, check if the meth is an
    # _translations field.
    if obj.nil? && (tr = meth.match(/(.*)_translations\z/)&.captures&.first)
      is_translation = true
      meth = document_class.database_field_name(tr)
    end

    curr = descend(i, curr, meth, field, num_meths, is_translation)

    i += 1
  end
  curr
end

#fetch_and_demongoize(obj, key, field) ⇒ Object (private)

Fetch the element from the given hash and demongoize it using the given field. If the obj is an array, map over it and call this method on all of its elements.

Parameters:

  • obj (Hash | Array<Hash>)

    The hash or array of hashes to fetch from.

  • key (String)

    The key to fetch from the hash.

  • field (Field)

    The field to use for demongoization.

Returns:

  • (Object)

    The demongoized value.

[ GitHub ]

  
# File 'lib/mongoid/pluckable.rb', line 49

def fetch_and_demongoize(obj, key, field)
  if obj.is_a?(Array)
    obj.map { |doc| fetch_and_demongoize(doc, key, field) }
  else
    value = obj.try(:fetch, key, nil)
    field ? field.demongoize(value) : value.class.demongoize(value)
  end
end

#pluck_from_documents(documents, field_names, document_class: klass) (private)

Plucks the given field names from the given documents.

[ GitHub ]

  
# File 'lib/mongoid/pluckable.rb', line 33

def pluck_from_documents(documents, field_names, document_class: klass)
  documents.reduce([]) do |plucked, doc|
    values = field_names.map { |name| extract_value(doc, name.to_s, document_class) }
    plucked << ((values.size == 1) ? values.first : values)
  end
end

#prepare_pluck(field_names, document_class: klass, prepare_projection: false) (private)

Prepares the field names for plucking by normalizing them to their database field names. Also prepares a projection hash if requested.

[ GitHub ]

  
# File 'lib/mongoid/pluckable.rb', line 14

def prepare_pluck(field_names, document_class: klass, prepare_projection: false)
  normalized_field_names = []
  projection = {}

  field_names.each do |f|
    db_fn = document_class.database_field_name(f)
    normalized_field_names.push(db_fn)

    next unless prepare_projection

    cleaned_name = document_class.cleanse_localized_field_names(f)
    canonical_name = document_class.database_field_name(cleaned_name)
    projection[canonical_name] = true
  end

  { field_names: normalized_field_names, projection: projection }
end