mongory 0.3.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +65 -0
- data/README.md +37 -7
- data/examples/benchmark-rails.rb +52 -0
- data/examples/benchmark.rb +79 -18
- data/lib/generators/mongory/matcher/matcher_generator.rb +1 -1
- data/lib/mongory/converters/abstract_converter.rb +22 -32
- data/lib/mongory/converters/condition_converter.rb +7 -4
- data/lib/mongory/converters/data_converter.rb +18 -7
- data/lib/mongory/converters/key_converter.rb +43 -19
- data/lib/mongory/converters/value_converter.rb +24 -19
- data/lib/mongory/matchers/abstract_matcher.rb +94 -32
- data/lib/mongory/matchers/abstract_multi_matcher.rb +16 -45
- data/lib/mongory/matchers/and_matcher.rb +38 -10
- data/lib/mongory/matchers/array_record_matcher.rb +54 -28
- data/lib/mongory/matchers/elem_match_matcher.rb +13 -9
- data/lib/mongory/matchers/eq_matcher.rb +12 -7
- data/lib/mongory/matchers/every_matcher.rb +20 -9
- data/lib/mongory/matchers/exists_matcher.rb +15 -14
- data/lib/mongory/matchers/field_matcher.rb +58 -38
- data/lib/mongory/matchers/gt_matcher.rb +15 -7
- data/lib/mongory/matchers/gte_matcher.rb +15 -7
- data/lib/mongory/matchers/hash_condition_matcher.rb +47 -25
- data/lib/mongory/matchers/in_matcher.rb +12 -10
- data/lib/mongory/matchers/literal_matcher.rb +42 -48
- data/lib/mongory/matchers/lt_matcher.rb +15 -7
- data/lib/mongory/matchers/lte_matcher.rb +15 -7
- data/lib/mongory/matchers/ne_matcher.rb +12 -7
- data/lib/mongory/matchers/nin_matcher.rb +12 -9
- data/lib/mongory/matchers/not_matcher.rb +9 -5
- data/lib/mongory/matchers/or_matcher.rb +42 -13
- data/lib/mongory/matchers/present_matcher.rb +14 -15
- data/lib/mongory/matchers/regex_matcher.rb +37 -22
- data/lib/mongory/matchers.rb +0 -1
- data/lib/mongory/query_builder.rb +88 -26
- data/lib/mongory/query_matcher.rb +39 -12
- data/lib/mongory/query_operator.rb +1 -1
- data/lib/mongory/utils/context.rb +41 -0
- data/lib/mongory/utils/debugger.rb +6 -4
- data/lib/mongory/utils.rb +1 -0
- data/lib/mongory/version.rb +1 -1
- data/lib/mongory.rb +3 -3
- data/mongory.gemspec +3 -3
- metadata +9 -10
- data/lib/mongory/matchers/README.md +0 -57
- data/lib/mongory/matchers/abstract_operator_matcher.rb +0 -46
- data/lib/mongory-rb.rb +0 -3
@@ -2,18 +2,22 @@
|
|
2
2
|
|
3
3
|
module Mongory
|
4
4
|
module Matchers
|
5
|
-
# FieldMatcher
|
6
|
-
# using a field (or index) and then delegating the match to LiteralMatcher logic.
|
5
|
+
# FieldMatcher handles field-level matching by extracting and comparing field values.
|
7
6
|
#
|
8
|
-
#
|
9
|
-
#
|
7
|
+
# This matcher is responsible for:
|
8
|
+
# 1. Extracting field values from records using dot notation
|
9
|
+
# 2. Converting extracted values if needed
|
10
|
+
# 3. Delegating the actual comparison to a submatcher
|
10
11
|
#
|
11
|
-
#
|
12
|
-
#
|
12
|
+
# It supports:
|
13
|
+
# - Hash records with string/symbol keys
|
14
|
+
# - Array records with numeric indices
|
15
|
+
# - Objects that respond to `[]`
|
13
16
|
#
|
14
|
-
# @example
|
15
|
-
# matcher = FieldMatcher.build(
|
16
|
-
# matcher.match?({ age
|
17
|
+
# @example Basic field matching
|
18
|
+
# matcher = FieldMatcher.build('age', 30)
|
19
|
+
# matcher.match?({ 'age' => 30 }) #=> true
|
20
|
+
# matcher.match?({ age: 30 }) #=> true
|
17
21
|
#
|
18
22
|
# @see LiteralMatcher
|
19
23
|
class FieldMatcher < LiteralMatcher
|
@@ -29,16 +33,18 @@ module Mongory
|
|
29
33
|
::Symbol
|
30
34
|
].freeze
|
31
35
|
|
32
|
-
# Initializes
|
36
|
+
# Initializes a new field matcher.
|
33
37
|
#
|
34
|
-
# @param field [
|
35
|
-
# @param condition [Object] the condition to match
|
36
|
-
|
38
|
+
# @param field [String, Symbol] the field to match against
|
39
|
+
# @param condition [Object] the condition to match with
|
40
|
+
# @param context [Context] the query context
|
41
|
+
def initialize(field, condition, context: Context.new)
|
37
42
|
@field = field
|
38
|
-
super(condition)
|
43
|
+
super(condition, context: context)
|
39
44
|
end
|
40
45
|
|
41
|
-
#
|
46
|
+
# Creates a raw Proc that performs the field matching operation.
|
47
|
+
# The Proc extracts the field value and delegates to the submatcher.
|
42
48
|
#
|
43
49
|
# This method first ensures the record is structurally eligible for field extraction—
|
44
50
|
# it must be a Hash, Array, or respond to `[]`. If the structure does not allow for
|
@@ -54,9 +60,6 @@ module Mongory
|
|
54
60
|
# Once the value is extracted, it is passed through the data converter
|
55
61
|
# and matched against the condition via the superclass.
|
56
62
|
#
|
57
|
-
# @param record [Object] the input data structure to be matched
|
58
|
-
# @return [Boolean] true if the extracted field value matches the condition; false otherwise
|
59
|
-
#
|
60
63
|
# @example Matching a Hash with a nil field value
|
61
64
|
# matcher = Mongory::QueryMatcher.new(a: nil)
|
62
65
|
# matcher.match?({ a: nil }) # => true
|
@@ -72,27 +75,44 @@ module Mongory
|
|
72
75
|
# @example Hash with symbol key, matcher uses string key
|
73
76
|
# matcher = Mongory::QueryMatcher.new('a' => 123)
|
74
77
|
# matcher.match?({ a: 123 }) # => true
|
75
|
-
def match(record)
|
76
|
-
sub_record =
|
77
|
-
case record
|
78
|
-
when Hash
|
79
|
-
record.fetch(@field) do
|
80
|
-
record.fetch(@field.to_sym, KEY_NOT_FOUND)
|
81
|
-
end
|
82
|
-
when Array
|
83
|
-
record.fetch(@field, KEY_NOT_FOUND)
|
84
|
-
when KEY_NOT_FOUND, *CLASSES_NOT_ALLOW_TO_DIG
|
85
|
-
return false
|
86
|
-
else
|
87
|
-
return false unless record.respond_to?(:[])
|
88
78
|
|
89
|
-
|
90
|
-
|
79
|
+
# Creates a raw Proc that performs the field-based matching operation.
|
80
|
+
# The Proc extracts the field value and delegates matching to the superclass.
|
81
|
+
#
|
82
|
+
# @return [Proc] A proc that performs field-based matching with context awareness
|
83
|
+
# @note The proc handles field extraction and delegates matching to the superclass
|
84
|
+
def raw_proc
|
85
|
+
super_proc = super
|
86
|
+
field = @field
|
87
|
+
need_convert = @context.need_convert
|
88
|
+
data_converter = Mongory.data_converter
|
89
|
+
|
90
|
+
Proc.new do |record|
|
91
|
+
sub_record =
|
92
|
+
case record
|
93
|
+
when Hash
|
94
|
+
record.fetch(field) do
|
95
|
+
record.fetch(field.to_sym, KEY_NOT_FOUND)
|
96
|
+
end
|
97
|
+
when Array
|
98
|
+
record.fetch(field, KEY_NOT_FOUND)
|
99
|
+
when KEY_NOT_FOUND, *CLASSES_NOT_ALLOW_TO_DIG
|
100
|
+
next false
|
101
|
+
else
|
102
|
+
next false unless record.respond_to?(:[])
|
91
103
|
|
92
|
-
|
104
|
+
record[field]
|
105
|
+
end
|
106
|
+
|
107
|
+
sub_record = data_converter.convert(sub_record) if need_convert
|
108
|
+
super_proc.call(sub_record)
|
109
|
+
end
|
93
110
|
end
|
94
111
|
|
95
|
-
#
|
112
|
+
# Returns a unique key for this matcher, including the field name.
|
113
|
+
# Used for deduplication in multi-matchers.
|
114
|
+
#
|
115
|
+
# @return [String] a unique key for this matcher
|
96
116
|
# @see AbstractMultiMatcher#matchers
|
97
117
|
def uniq_key
|
98
118
|
super + "field:#{@field}"
|
@@ -100,9 +120,9 @@ module Mongory
|
|
100
120
|
|
101
121
|
private
|
102
122
|
|
103
|
-
# Returns a single-line summary of the
|
123
|
+
# Returns a single-line summary of the field matcher including the field and condition.
|
104
124
|
#
|
105
|
-
# @return [String]
|
125
|
+
# @return [String] a formatted title for tree display
|
106
126
|
def tree_title
|
107
127
|
"Field: #{@field.inspect} to match: #{@condition.inspect}"
|
108
128
|
end
|
@@ -111,7 +131,7 @@ module Mongory
|
|
111
131
|
#
|
112
132
|
# @param record [Object] the input record
|
113
133
|
# @param result [Boolean] match result
|
114
|
-
# @return [String] formatted debug string
|
134
|
+
# @return [String] formatted debug string with highlighted field
|
115
135
|
def debug_display(record, result)
|
116
136
|
"#{self.class.name.split('::').last} #{colored_result(result)}, " \
|
117
137
|
"condition: #{@condition.inspect}, " \
|
@@ -6,7 +6,7 @@ module Mongory
|
|
6
6
|
#
|
7
7
|
# It returns true if the record is strictly greater than the condition.
|
8
8
|
#
|
9
|
-
# Inherits core logic from
|
9
|
+
# Inherits core logic from AbstractMatcher, including
|
10
10
|
# error handling and optional preprocessing.
|
11
11
|
#
|
12
12
|
# @example
|
@@ -14,13 +14,21 @@ module Mongory
|
|
14
14
|
# matcher.match?(15) #=> true
|
15
15
|
# matcher.match?(10) #=> false
|
16
16
|
#
|
17
|
-
# @see
|
18
|
-
class GtMatcher <
|
19
|
-
#
|
17
|
+
# @see AbstractMatcher
|
18
|
+
class GtMatcher < AbstractMatcher
|
19
|
+
# Creates a raw Proc that performs the greater-than comparison.
|
20
|
+
# The Proc uses the `>` operator to compare values.
|
20
21
|
#
|
21
|
-
# @return [
|
22
|
-
|
23
|
-
|
22
|
+
# @return [Proc] A proc that performs greater-than comparison with error handling
|
23
|
+
# @note The proc includes error handling for invalid comparisons
|
24
|
+
def raw_proc
|
25
|
+
condition = @condition
|
26
|
+
|
27
|
+
Proc.new do |record|
|
28
|
+
record > condition
|
29
|
+
rescue StandardError
|
30
|
+
false
|
31
|
+
end
|
24
32
|
end
|
25
33
|
end
|
26
34
|
|
@@ -6,7 +6,7 @@ module Mongory
|
|
6
6
|
#
|
7
7
|
# It returns true if the record is greater than or equal to the condition value.
|
8
8
|
#
|
9
|
-
# Inherits comparison logic and error safety from
|
9
|
+
# Inherits comparison logic and error safety from AbstractMatcher.
|
10
10
|
#
|
11
11
|
# @example
|
12
12
|
# matcher = GteMatcher.build(10)
|
@@ -14,13 +14,21 @@ module Mongory
|
|
14
14
|
# matcher.match?(11) #=> true
|
15
15
|
# matcher.match?(9) #=> false
|
16
16
|
#
|
17
|
-
# @see
|
18
|
-
class GteMatcher <
|
19
|
-
#
|
17
|
+
# @see AbstractMatcher
|
18
|
+
class GteMatcher < AbstractMatcher
|
19
|
+
# Creates a raw Proc that performs the greater-than-or-equal comparison.
|
20
|
+
# The Proc uses the `>=` operator to compare values.
|
20
21
|
#
|
21
|
-
# @return [
|
22
|
-
|
23
|
-
|
22
|
+
# @return [Proc] A proc that performs greater-than-or-equal comparison with error handling
|
23
|
+
# @note The proc includes error handling for invalid comparisons
|
24
|
+
def raw_proc
|
25
|
+
condition = @condition
|
26
|
+
|
27
|
+
Proc.new do |record|
|
28
|
+
record >= condition
|
29
|
+
rescue StandardError
|
30
|
+
false
|
31
|
+
end
|
24
32
|
end
|
25
33
|
end
|
26
34
|
|
@@ -9,46 +9,68 @@ module Mongory
|
|
9
9
|
#
|
10
10
|
# Each subcondition is matched independently using the `:all?` strategy, meaning
|
11
11
|
# all subconditions must match for the entire HashConditionMatcher to succeed.
|
12
|
+
# For empty conditions, it returns true (using TRUE_PROC).
|
12
13
|
#
|
13
14
|
# This matcher plays a central role in dispatching symbolic query conditions
|
14
15
|
# to the appropriate field or operator matcher.
|
15
16
|
#
|
16
|
-
# @example
|
17
|
+
# @example Basic field matching
|
17
18
|
# matcher = HashConditionMatcher.build({ age: { :$gt => 30 }, active: true })
|
18
19
|
# matcher.match?(record) #=> true only if all subconditions match
|
19
20
|
#
|
21
|
+
# @example Empty conditions
|
22
|
+
# matcher = HashConditionMatcher.build({})
|
23
|
+
# matcher.match?(record) #=> true (uses TRUE_PROC)
|
24
|
+
#
|
20
25
|
# @see AbstractMultiMatcher
|
21
26
|
class HashConditionMatcher < AbstractMultiMatcher
|
22
27
|
enable_unwrap!
|
23
|
-
# Constructs the appropriate submatcher for a key-value pair.
|
24
|
-
# If the key is a registered operator, dispatches to the corresponding matcher.
|
25
|
-
# Otherwise, assumes the key is a field path and uses FieldMatcher.
|
26
28
|
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
# @return [
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
29
|
+
# Creates a raw Proc that performs the hash condition matching operation.
|
30
|
+
# The Proc combines all submatcher Procs and returns true only if all match.
|
31
|
+
# For empty conditions, returns TRUE_PROC.
|
32
|
+
#
|
33
|
+
# @return [Proc] a Proc that performs the hash condition matching operation
|
34
|
+
def raw_proc
|
35
|
+
return TRUE_PROC if matchers.empty?
|
36
|
+
|
37
|
+
combine_procs(*matchers.map(&:to_proc))
|
38
|
+
end
|
39
|
+
|
40
|
+
# Recursively combines multiple matcher procs with AND logic.
|
41
|
+
# This method optimizes the combination of multiple matchers by building
|
42
|
+
# a balanced tree of AND operations.
|
43
|
+
#
|
44
|
+
# @param left [Proc] The left matcher proc to combine
|
45
|
+
# @param rest [Array<Proc>] The remaining matcher procs to combine
|
46
|
+
# @return [Proc] A new proc that combines all matchers with AND logic
|
47
|
+
# @example
|
48
|
+
# combine_procs(proc1, proc2, proc3)
|
49
|
+
# #=> proc { |record| proc1.call(record) && proc2.call(record) && proc3.call(record) }
|
50
|
+
def combine_procs(left, *rest)
|
51
|
+
return left if rest.empty?
|
52
|
+
|
53
|
+
right = combine_procs(*rest)
|
54
|
+
Proc.new do |record|
|
55
|
+
left.call(record) && right.call(record)
|
43
56
|
end
|
44
57
|
end
|
45
58
|
|
46
|
-
#
|
47
|
-
# Uses `:all?`, meaning all conditions must be satisfied.
|
59
|
+
# Returns the list of matchers for each key-value pair in the condition.
|
48
60
|
#
|
49
|
-
#
|
50
|
-
|
51
|
-
|
61
|
+
# For each pair:
|
62
|
+
# - If the key is a registered operator, uses the corresponding matcher
|
63
|
+
# - Otherwise, wraps the value in a FieldMatcher for field path matching
|
64
|
+
#
|
65
|
+
# @return [Array<AbstractMatcher>] List of matchers for each condition
|
66
|
+
define_instance_cache_method(:matchers) do
|
67
|
+
@condition.map do |key, value|
|
68
|
+
if (matcher_class = Matchers.lookup(key))
|
69
|
+
matcher_class.build(value, context: @context)
|
70
|
+
else
|
71
|
+
FieldMatcher.build(key, value, context: @context)
|
72
|
+
end
|
73
|
+
end
|
52
74
|
end
|
53
75
|
end
|
54
76
|
end
|
@@ -24,17 +24,19 @@ module Mongory
|
|
24
24
|
#
|
25
25
|
# @see AbstractMatcher
|
26
26
|
class InMatcher < AbstractMatcher
|
27
|
-
#
|
28
|
-
#
|
27
|
+
# Creates a raw Proc that performs the in-matching operation.
|
28
|
+
# The Proc checks if any element of the record is in the condition array.
|
29
29
|
#
|
30
|
-
# @
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
30
|
+
# @return [Proc] a Proc that performs the in-matching operation
|
31
|
+
def raw_proc
|
32
|
+
condition = @condition
|
33
|
+
|
34
|
+
Proc.new do |record|
|
35
|
+
if record.is_a?(Array)
|
36
|
+
is_present?(condition & record)
|
37
|
+
else
|
38
|
+
condition.include?(record)
|
39
|
+
end
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
@@ -2,55 +2,49 @@
|
|
2
2
|
|
3
3
|
module Mongory
|
4
4
|
module Matchers
|
5
|
-
# LiteralMatcher
|
5
|
+
# LiteralMatcher handles direct value comparison with special array handling.
|
6
6
|
#
|
7
|
-
# This matcher
|
8
|
-
#
|
7
|
+
# This matcher is used when a condition is a literal value (not an operator).
|
8
|
+
# It handles both direct equality comparison and array-record scenarios.
|
9
9
|
#
|
10
|
-
#
|
10
|
+
# For array records:
|
11
|
+
# - Uses ArrayRecordMatcher to check if any element matches
|
12
|
+
# For non-array records:
|
13
|
+
# - Uses appropriate matcher based on condition type (Hash, Regexp, nil, etc.)
|
11
14
|
#
|
12
|
-
# @example
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
# { tags: [1, 2, 3] } # Array literal → ArrayRecordMatcher
|
17
|
-
# { email: /@gmail\\.com/i } # Regexp literal → RegexMatcher
|
18
|
-
# { info: nil } # nil literal → nil_matcher (matches null or missing)
|
15
|
+
# @example Basic equality matching
|
16
|
+
# matcher = LiteralMatcher.build(42)
|
17
|
+
# matcher.match?(42) #=> true
|
18
|
+
# matcher.match?([42, 43]) #=> true (array contains 42)
|
19
19
|
#
|
20
|
-
# @
|
21
|
-
#
|
20
|
+
# @example Regexp matching
|
21
|
+
# matcher = LiteralMatcher.build(/foo/)
|
22
|
+
# matcher.match?("foo") #=> true
|
23
|
+
# matcher.match?(["foobar"]) #=> true
|
22
24
|
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
# - TrueClass / FalseClass
|
28
|
-
# - NilClass → delegates to nil_matcher
|
29
|
-
# - Regexp → delegates to RegexMatcher
|
30
|
-
# - Array → delegates to ArrayRecordMatcher
|
31
|
-
# - Hash → delegates to HashConditionMatcher (if treated as sub-query)
|
32
|
-
# - Other unrecognized values → fallback to equality match (==)
|
25
|
+
# @example Hash condition matching
|
26
|
+
# matcher = LiteralMatcher.build({ '$gt' => 10 })
|
27
|
+
# matcher.match?(15) #=> true
|
28
|
+
# matcher.match?([5, 15]) #=> true
|
33
29
|
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
# - Nested paths like `"a.b.c"` → handled by FieldMatcher
|
37
|
-
# - Query combinators like `$or`, `$and`, `$not` → handled by corresponding matchers
|
38
|
-
#
|
39
|
-
# @see Mongory::Matchers::RegexMatcher
|
40
|
-
# @see Mongory::Matchers::OrMatcher
|
41
|
-
# @see Mongory::Matchers::ArrayRecordMatcher
|
42
|
-
# @see Mongory::Matchers::HashConditionMatcher
|
30
|
+
# @see AbstractMatcher
|
31
|
+
# @see ArrayRecordMatcher
|
43
32
|
class LiteralMatcher < AbstractMatcher
|
44
|
-
#
|
33
|
+
# Creates a raw Proc that performs the literal matching operation.
|
34
|
+
# The Proc handles both array and non-array records appropriately.
|
45
35
|
#
|
46
|
-
# @
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
36
|
+
# @return [Proc] a Proc that performs the literal matching operation
|
37
|
+
def raw_proc
|
38
|
+
array_record_proc = nil
|
39
|
+
dispatched_proc = dispatched_matcher.to_proc
|
40
|
+
|
41
|
+
Proc.new do |record|
|
42
|
+
if record.is_a?(Array)
|
43
|
+
array_record_proc ||= array_record_matcher.to_proc
|
44
|
+
array_record_proc.call(record)
|
45
|
+
else
|
46
|
+
dispatched_proc.call(record)
|
47
|
+
end
|
54
48
|
end
|
55
49
|
end
|
56
50
|
|
@@ -77,16 +71,16 @@ module Mongory
|
|
77
71
|
define_matcher(:dispatched) do
|
78
72
|
case @condition
|
79
73
|
when Hash
|
80
|
-
HashConditionMatcher.build(@condition)
|
74
|
+
HashConditionMatcher.build(@condition, context: @context)
|
81
75
|
when Regexp
|
82
|
-
RegexMatcher.build(@condition)
|
76
|
+
RegexMatcher.build(@condition, context: @context)
|
83
77
|
when nil
|
84
78
|
OrMatcher.build([
|
85
79
|
{ '$exists' => false },
|
86
80
|
{ '$eq' => nil }
|
87
|
-
])
|
81
|
+
], context: @context)
|
88
82
|
else
|
89
|
-
EqMatcher.build(@condition)
|
83
|
+
EqMatcher.build(@condition, context: @context)
|
90
84
|
end
|
91
85
|
end
|
92
86
|
|
@@ -96,7 +90,7 @@ module Mongory
|
|
96
90
|
# @return [ArrayRecordMatcher] the matcher used to match array-type records
|
97
91
|
# @!method array_record_matcher
|
98
92
|
define_matcher(:array_record) do
|
99
|
-
ArrayRecordMatcher.build(@condition)
|
93
|
+
ArrayRecordMatcher.build(@condition, context: @context)
|
100
94
|
end
|
101
95
|
|
102
96
|
# Validates the nested condition matcher, if applicable.
|
@@ -109,8 +103,8 @@ module Mongory
|
|
109
103
|
# Outputs the matcher tree by selecting either collection or condition matcher.
|
110
104
|
# Delegates `render_tree` to whichever submatcher was active.
|
111
105
|
#
|
112
|
-
# @param prefix [String]
|
113
|
-
# @param is_last [Boolean]
|
106
|
+
# @param prefix [String] the prefix string for tree rendering
|
107
|
+
# @param is_last [Boolean] whether this is the last node in the tree
|
114
108
|
# @return [void]
|
115
109
|
def render_tree(prefix = '', is_last: true)
|
116
110
|
super
|
@@ -6,7 +6,7 @@ module Mongory
|
|
6
6
|
#
|
7
7
|
# It returns true if the record is strictly less than the condition value.
|
8
8
|
#
|
9
|
-
# This matcher inherits from
|
9
|
+
# This matcher inherits from AbstractMatcher and uses the `<` operator.
|
10
10
|
#
|
11
11
|
# @example
|
12
12
|
# matcher = LtMatcher.build(10)
|
@@ -14,13 +14,21 @@ module Mongory
|
|
14
14
|
# matcher.match?(10) #=> false
|
15
15
|
# matcher.match?(11) #=> false
|
16
16
|
#
|
17
|
-
# @see
|
18
|
-
class LtMatcher <
|
19
|
-
#
|
17
|
+
# @see AbstractMatcher
|
18
|
+
class LtMatcher < AbstractMatcher
|
19
|
+
# Creates a raw Proc that performs the less-than comparison.
|
20
|
+
# The Proc uses the `<` operator to compare values.
|
20
21
|
#
|
21
|
-
# @return [
|
22
|
-
|
23
|
-
|
22
|
+
# @return [Proc] A proc that performs less-than comparison with error handling
|
23
|
+
# @note The proc includes error handling for invalid comparisons
|
24
|
+
def raw_proc
|
25
|
+
condition = @condition
|
26
|
+
|
27
|
+
Proc.new do |record|
|
28
|
+
record < condition
|
29
|
+
rescue StandardError
|
30
|
+
false
|
31
|
+
end
|
24
32
|
end
|
25
33
|
end
|
26
34
|
|
@@ -6,7 +6,7 @@ module Mongory
|
|
6
6
|
#
|
7
7
|
# It returns true if the record is less than or equal to the condition value.
|
8
8
|
#
|
9
|
-
# This matcher inherits from
|
9
|
+
# This matcher inherits from AbstractMatcher and uses the `<=` operator.
|
10
10
|
#
|
11
11
|
# @example
|
12
12
|
# matcher = LteMatcher.build(10)
|
@@ -14,13 +14,21 @@ module Mongory
|
|
14
14
|
# matcher.match?(10) #=> true
|
15
15
|
# matcher.match?(11) #=> false
|
16
16
|
#
|
17
|
-
# @see
|
18
|
-
class LteMatcher <
|
19
|
-
#
|
17
|
+
# @see AbstractMatcher
|
18
|
+
class LteMatcher < AbstractMatcher
|
19
|
+
# Creates a raw Proc that performs the less-than-or-equal comparison.
|
20
|
+
# The Proc uses the `<=` operator to compare values.
|
20
21
|
#
|
21
|
-
# @return [
|
22
|
-
|
23
|
-
|
22
|
+
# @return [Proc] A proc that performs less-than-or-equal comparison with error handling
|
23
|
+
# @note The proc includes error handling for invalid comparisons
|
24
|
+
def raw_proc
|
25
|
+
condition = @condition
|
26
|
+
|
27
|
+
Proc.new do |record|
|
28
|
+
record <= condition
|
29
|
+
rescue StandardError
|
30
|
+
false
|
31
|
+
end
|
24
32
|
end
|
25
33
|
end
|
26
34
|
|
@@ -6,7 +6,7 @@ module Mongory
|
|
6
6
|
#
|
7
7
|
# It returns true if the record is *not equal* to the condition.
|
8
8
|
#
|
9
|
-
# This matcher inherits its logic from
|
9
|
+
# This matcher inherits its logic from AbstractMatcher
|
10
10
|
# and uses Ruby's `!=` operator for comparison.
|
11
11
|
#
|
12
12
|
# @example
|
@@ -14,13 +14,18 @@ module Mongory
|
|
14
14
|
# matcher.match?(41) #=> true
|
15
15
|
# matcher.match?(42) #=> false
|
16
16
|
#
|
17
|
-
# @see
|
18
|
-
class NeMatcher <
|
19
|
-
#
|
17
|
+
# @see AbstractMatcher
|
18
|
+
class NeMatcher < AbstractMatcher
|
19
|
+
# Creates a raw Proc that performs the not-equal comparison.
|
20
|
+
# The Proc uses the `!=` operator to compare values.
|
20
21
|
#
|
21
|
-
# @return [
|
22
|
-
def
|
23
|
-
|
22
|
+
# @return [Proc] A proc that performs not-equal comparison
|
23
|
+
def raw_proc
|
24
|
+
condition = @condition
|
25
|
+
|
26
|
+
Proc.new do |record|
|
27
|
+
record != condition
|
28
|
+
end
|
24
29
|
end
|
25
30
|
end
|
26
31
|
|
@@ -24,16 +24,19 @@ module Mongory
|
|
24
24
|
#
|
25
25
|
# @see AbstractMatcher
|
26
26
|
class NinMatcher < AbstractMatcher
|
27
|
-
#
|
27
|
+
# Creates a raw Proc that performs the not-in matching operation.
|
28
|
+
# The Proc checks if the record has no elements in common with the condition array.
|
28
29
|
#
|
29
|
-
# @
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
30
|
+
# @return [Proc] A proc that performs not-in matching
|
31
|
+
def raw_proc
|
32
|
+
condition = @condition
|
33
|
+
|
34
|
+
Proc.new do |record|
|
35
|
+
if record.is_a?(Array)
|
36
|
+
is_blank?(condition & record)
|
37
|
+
else
|
38
|
+
!condition.include?(record)
|
39
|
+
end
|
37
40
|
end
|
38
41
|
end
|
39
42
|
|
@@ -18,12 +18,16 @@ module Mongory
|
|
18
18
|
#
|
19
19
|
# @see LiteralMatcher
|
20
20
|
class NotMatcher < LiteralMatcher
|
21
|
-
#
|
21
|
+
# Creates a raw Proc that performs the not-matching operation.
|
22
|
+
# The Proc inverts the result of the wrapped matcher.
|
22
23
|
#
|
23
|
-
# @
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
# @return [Proc] A proc that performs not-matching
|
25
|
+
def raw_proc
|
26
|
+
super_proc = super
|
27
|
+
|
28
|
+
Proc.new do |record|
|
29
|
+
!super_proc.call(record)
|
30
|
+
end
|
27
31
|
end
|
28
32
|
end
|
29
33
|
|