Module: Mongoid::Matcher::EqImpl Private

Defined in:
lib/mongoid/matcher/eq_impl.rb

Overview

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.

This module is used by $eq and other operators that need to perform the matching that $eq performs (for example, $ne which negates the result of $eq). Unlike $eq this module takes an original operator as an additional argument to matches? to provide the correct exception messages reflecting the operator that was first invoked.

Class Method Summary collapse

Class Method Details

.matches?(exists, value, condition, original_operator) ⇒ true | false, Boolean

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.

Returns whether a value satisfies an $eq (or similar) expression.

Parameters:

  • exists (true | false)

    Not used.

  • value (Object)

    The value to check.

  • condition (Object | Range)

    The equality condition predicate.

  • original_operator (String)

    Operator to use in exception messages.

Returns:

  • (true | false)

    Whether the value matches.

  • (Boolean)


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/mongoid/matcher/eq_impl.rb', line 24

module_function def matches?(exists, value, condition, original_operator)
  case condition
  when Range
    # Since $ne invokes $eq, the exception message needs to handle
    # both operators.
    raise Errors::InvalidQuery, "Range is not supported as an argument to '#{original_operator}'"
=begin
    if value.is_a?(Array)
      value.any? { |elt| condition.include?(elt) }
    else
      condition.include?(value)
    end
=end
  else
    # When doing a comparison with Time objects, compare using millisecond precision
    if value.kind_of?(Time) && condition.kind_of?(Time)
      time_eq?(value, condition)
    elsif value.is_a?(Array) && condition.kind_of?(Time)
      value.map do |v|
        if v.kind_of?(Time)
          time_rounded_to_millis(v)
        else
          v
        end
      end.include?(time_rounded_to_millis(condition))
    else
      value == condition ||
      value.is_a?(Array) && value.include?(condition)
    end
  end
end

.time_eq?(time_a, time_b) ⇒ true | false, Boolean

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.

Per www.mongodb.com/docs/ruby-driver/current/tutorials/bson-v4/#time-instances, > Times in BSON (and MongoDB) can only have millisecond precision. When Ruby Time instances are serialized to BSON or Extended JSON, the times are floored to the nearest millisecond.

> Because of this flooring, applications are strongly recommended to perform all time calculations using integer math, as inexactness of floating point calculations may produce unexpected results.

As such, perform a similar operation to what the bson-ruby gem does.

Parameters:

  • time_a (Time)

    The first time value.

  • time_b (Time)

    The second time value.

Returns:

  • (true | false)

    Whether the two times are equal to the millisecond.

  • (Boolean)


70
71
72
# File 'lib/mongoid/matcher/eq_impl.rb', line 70

module_function def time_eq?(time_a, time_b)
  time_rounded_to_millis(time_a) == time_rounded_to_millis(time_b)
end

.time_rounded_to_millis(time) ⇒ 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.

Rounds a time value to nearest millisecond.

Parameters:

  • time (Time)

    The time value.

Returns:

  • (true | false)

    The time rounded to the millisecond.



79
80
81
# File 'lib/mongoid/matcher/eq_impl.rb', line 79

module_function def time_rounded_to_millis(time)
  return time._bson_to_i * 1000 + time.usec.divmod(1000).first
end