module Mongoid::Matchable

This module contains all the behavior for Ruby implementations of MongoDB selectors.

@since 4.0.0

Constants

MATCHERS

Hash lookup for the matcher for a specific operation.

@since 1.0.0

Private Class Methods

extract_attribute(document, key) click to toggle source

Extract the attribute from the key, being smarter about dot notation.

@api private

@example Extract the attribute.

strategy.extract_attribute(doc, "info.field")

@param [ Document ] document The document. @param [ String ] key The key.

@return [ Object ] The value of the attribute.

@since 2.2.1 @api private

# File lib/mongoid/matchable.rb, line 153
def extract_attribute(document, key)
  if (key_string = key.to_s) =~ /.+\..+/
    key_string.split('.').inject(document.send(:as_attributes)) do |_attribs, _key|
      if _attribs.is_a?(::Array)
        if _key =~ /\A\d+\z/ && _attribs.none? {|doc| doc.is_a?(Hash)}
          _attribs.try(:[], _key.to_i)
        else
          _attribs.map { |doc| doc.try(:[], _key) }
        end
      else
        _attribs.try(:[], _key)
      end
    end
  else
    if document.is_a?(Hash)
      document[key_string]
    else
      document.attributes[key_string]
    end
  end
end
matcher(document, key, value) click to toggle source

Get the matcher for the supplied key and value. Will determine the class name from the key.

@api private

@example Get the matcher.

Matchable.matcher(document, :title, { "$in" => [ "test" ] })

@param [ Document ] document The document to check. @param [ Symbol, String ] key The field name. @param [ Object, Hash ] value The value or selector.

@return [ Matcher ] The matcher.

@since 2.0.0.rc.7

# File lib/mongoid/matchable.rb, line 117
def matcher(document, key, value)
  if value.is_a?(Hash)
    matcher = MATCHERS[value.keys.first]
    if matcher
      matcher.new(extract_attribute(document, key))
    else
      Default.new(extract_attribute(document, key))
    end
  elsif value.regexp?
    Regexp.new(extract_attribute(document, key))
  else
    case key.to_s
      when "$or" then Or.new(value, document)
      when "$and" then And.new(value, document)
      when "$nor" then Nor.new(value, document)
      else Default.new(extract_attribute(document, key))
    end
  end
end

Public Instance Methods

_matches?(selector) click to toggle source

Determines if this document has the attributes to match the supplied MongoDB selector. Used for matching on embedded associations.

@example Does the document match?

document._matches?(:title => { "$in" => [ "test" ] })

@param [ Hash ] selector The MongoDB selector.

@return [ true, false ] True if matches, false if not.

@since 1.0.0

# File lib/mongoid/matchable.rb, line 63
def _matches?(selector)
  selector.each_pair do |key, value|
    if value.is_a?(Hash)
      value.each do |item|
        if item[0].to_s == "$not".freeze
          item = item[1]
          return false if matcher(key, item)._matches?(item)
        else
          return false unless matcher(key, Hash[*item])._matches?(Hash[*item])
        end
      end
    else
      return false unless matcher(key, value)._matches?(value)
    end
  end
  true
end

Private Instance Methods

matcher(key, value) click to toggle source

Get the matcher for the supplied key and value. Will determine the class name from the key.

@example Get the matcher.

document.matcher(:title, { "$in" => [ "test" ] })

@param [ Symbol, String ] key The field name. @param [ Object, Hash ] value The value or selector.

@return [ Matcher ] The matcher.

@since 2.0.0.rc.7 @api private

# File lib/mongoid/matchable.rb, line 96
def matcher(key, value)
  Matchable.matcher(self, key, value)
end