Module: Mongoid::Matcher Private

Defined in:
lib/mongoid/matcher.rb,
lib/mongoid/matcher/eq.rb,
lib/mongoid/matcher/gt.rb,
lib/mongoid/matcher/in.rb,
lib/mongoid/matcher/lt.rb,
lib/mongoid/matcher/ne.rb,
lib/mongoid/matcher/or.rb,
lib/mongoid/matcher/all.rb,
lib/mongoid/matcher/and.rb,
lib/mongoid/matcher/gte.rb,
lib/mongoid/matcher/lte.rb,
lib/mongoid/matcher/nin.rb,
lib/mongoid/matcher/nor.rb,
lib/mongoid/matcher/not.rb,
lib/mongoid/matcher/size.rb,
lib/mongoid/matcher/regex.rb,
lib/mongoid/matcher/exists.rb,
lib/mongoid/matcher/eq_impl.rb,
lib/mongoid/matcher/elem_match.rb,
lib/mongoid/matcher/expression.rb,
lib/mongoid/matcher/field_operator.rb,
lib/mongoid/matcher/field_expression.rb,
lib/mongoid/matcher/eq_impl_with_regexp.rb,
lib/mongoid/matcher/expression_operator.rb,
lib/mongoid/matcher/elem_match_expression.rb

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Defined Under Namespace

Modules: All, And, ElemMatch, ElemMatchExpression, Eq, EqImpl, EqImplWithRegexp, Exists, Expression, ExpressionOperator, FieldExpression, FieldOperator, Gt, Gte, In, Lt, Lte, Ne, Nin, Nor, Not, Or, Regex, Size

Class Method Summary collapse

Class Method Details

.extract_attribute(document, key) ⇒ Array<true | false, Object | Array, true | false>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Extracts field values in the document at the specified key.

The document can be a Hash or a model instance.

The key is a valid MongoDB dot notation key. The following use cases are supported:

  • Simple field traversal (‘foo`) - retrieves the field `foo` in the current document.

  • Hash/embedded document field traversal (‘foo.bar`) - retrieves the field `foo` in the current document, then retrieves the field `bar` from the value of `foo`. Each path segment could descend into an embedded document or a hash field.

  • Array element retrieval (‘foo.N`) - retrieves the Nth array element from the field `foo` which must be an array. N must be a non-negative integer.

  • Array traversal (‘foo.bar`) - if `foo` is an array field, and the elements of `foo` are hashes or embedded documents, this returns an array of values of the `bar` field in each of the hashes in the `foo` array.

The return value is a two-element array. The first element is the value retrieved, or an array of values. The second element is a boolean flag indicating whether an array was expanded at any point during the key traversal (because the respective document field was an array).

Parameters:

  • document (Document | Hash)

    The document to extract from.

  • key (String)

    The key path to extract.

Returns:

  • (Array<true | false, Object | Array, true | false>)

    Whether the value existed in the document, the extracted value and the array expansion flag.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/mongoid/matcher.rb', line 38

module_function def extract_attribute(document, key)
  if document.respond_to?(:as_attributes, true)
    # If a document has hash fields, as_attributes would keep those fields
    # as Hash instances which do not offer indifferent access.
    # Convert to BSON::Document to get indifferent access on hash fields.
    document = BSON::Document.new(document.send(:as_attributes))
  end

  src = document
  expanded = false
  exists = true

  key.to_s.split('.').each do |field|
    if (index = field.to_i).to_s == field
      # Array indexing
      if Array === src
        exists = index < src.length
        src = src[index]
      else
        # Trying to index something that is not an array
        exists = false
        src = nil
      end
    else
      case src
      when nil
        exists = false
      when Hash
        exists = src.key?(field)
        src = src[field]
      when Array
        expanded = true
        exists = false
        new = []
        src.each do |doc|
          case doc
          when Hash
            if doc.key?(field)
              v = doc[field]
              case v
              when Array
                new += v
              else
                new += [v]
              end
              exists = true
            end
          else
            # Trying to hash index into a value that is not a hash
          end
        end
        src = new
      else
        # Trying to descend into a field that is not a hash using
        # dot notation.
        exists = false
        src = nil
      end
    end
  end

  [exists, src, expanded]
end