module Mongoid::Criteria::Queryable::Storable

def add_field_expression(field, value)

Returns:
  • (Storable) - self.

Parameters:
  • value (Object) -- The field value.
  • field (String) -- The field name.
def add_field_expression(field, value)
  unless field.is_a?(String)
    raise ArgumentError, "Field must be a string: #{field}"
  end
  if field.start_with?('$')
    raise ArgumentError, "Field cannot be an operator (i.e. begin with $): #{field}"
  end
  if selector[field]
    # We already have a restriction by the field we are trying
    # to restrict, combine the restrictions.
    if value.is_a?(Hash) && selector[field].is_a?(Hash) &&
      value.keys.all? { |key|
        key_s = key.to_s
        key_s.start_with?('$') && !selector[field].keys.map(&:to_s).include?(key_s)
      }
    then
      # Multiple operators can be combined on the same field by
      # adding them to the existing hash.
      new_value = selector[field].merge(value)
      selector.store(field, new_value)
    elsif selector[field] != value
      add_operator_expression('$and', [{field => value}])
    end
  else
    selector.store(field, value)
  end
  self
end

def add_logical_operator_expression(operator, op_expr)

Returns:
  • (Storable) - self.

Parameters:
  • op_expr (Array) -- Operator value to add.
  • operator (String) -- The operator to add.
def add_logical_operator_expression(operator, op_expr)
  unless operator.is_a?(String)
    raise ArgumentError, "Operator must be a string: #{operator}"
  end
  unless %w($and $nor $or).include?(operator)
    raise ArgumentError, "This method only handles logical operators ($and, $nor, $or). Operator given: #{operator}"
  end
  unless op_expr.is_a?(Array)
    raise Errors::InvalidQuery, "#{operator} argument must be an array: #{Errors::InvalidQuery.truncate_expr(op_expr)}"
  end
  if selector.length == 1 && selector.keys.first == operator
    new_value = selector.values.first + op_expr
    selector.store(operator, new_value)
  elsif operator == '$and' || selector.empty?
    # $and can always be added to top level and it will be combined
    # with whatever other conditions exist.
    if current_value = selector[operator]
      new_value = current_value + op_expr
      selector.store(operator, new_value)
    else
      selector.store(operator, op_expr)
    end
  else
    # Other operators need to be added separately
    if selector[operator]
      add_logical_operator_expression('$and', [operator => op_expr])
    else
      selector.store(operator, op_expr)
    end
  end
  self
end

def add_one_expression(field, value)

Returns:
  • (Storable) - self.

Parameters:
  • value (Object) -- Field value or operator expression.
  • field (String) -- Field name or operator name.
def add_one_expression(field, value)
  unless field.is_a?(String)
    raise ArgumentError, "Field must be a string: #{field}"
  end
  if field.start_with?('$')
    add_operator_expression(field, value)
  else
    add_field_expression(field, value)
  end
end

def add_operator_expression(operator, op_expr)

Returns:
  • (Storable) - self.

Parameters:
  • op_expr (Object) -- Operator value to add.
  • operator (String) -- The operator to add.
def add_operator_expression(operator, op_expr)
  unless operator.is_a?(String)
    raise ArgumentError, "Operator must be a string: #{operator}"
  end
  unless operator.start_with?('$')
    raise ArgumentError, "Operator must begin with $: #{operator}"
  end
  if %w($and $nor $or).include?(operator)
    return add_logical_operator_expression(operator, op_expr)
  end
  # For other operators, if the operator already exists in the
  # query, add the new condition with $and, otherwise add the
  # new condition to the top level.
  if selector[operator]
    add_logical_operator_expression('$and', [{operator => op_expr}])
  else
    selector.store(operator, op_expr)
  end
  self
end