Skip to content

Commit 1c00de5

Browse files
committed
RawValue should mongoize ranges rather than evolving them
1 parent b3cf1f9 commit 1c00de5

File tree

2 files changed

+48
-19
lines changed

2 files changed

+48
-19
lines changed

lib/mongoid/criteria/queryable/selector.rb

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def to_pipeline
7575

7676
# Get the store name and store value. If the value is of type range,
7777
# we need may need to change the store_name as well as the store_value,
78-
# therefore, we cannot just use the evole method.
78+
# therefore, we cannot just use the evolve method.
7979
#
8080
# @param [ String ] name The name of the field.
8181
# @param [ Object ] serializer The optional serializer for the field.
@@ -85,7 +85,7 @@ def to_pipeline
8585
def store_creds(name, serializer, value)
8686
store_name = localized_key(name, serializer)
8787
if Range === value
88-
evolve_range(store_name, serializer, value)
88+
evolve_top_level_range(store_name, serializer, value)
8989
else
9090
[ store_name, evolve(serializer, value) ]
9191
end
@@ -147,11 +147,14 @@ def evolve_multi(specs)
147147
#
148148
# @param [ Object ] serializer The optional serializer for the field.
149149
# @param [ Object ] value The value to serialize.
150+
# @param [ Object ] is_raw_value Indicates that the evolve should be
151+
# processed as a member of a Mongoid::RawValue. Used for recursion.
150152
#
151153
# @return [ Object ] The serialized object.
152-
def evolve(serializer, value)
154+
def evolve(serializer, value, is_raw_value = false)
153155

154156
if value.is_a?(Mongoid::RawValue)
157+
is_raw_value = true
155158
value = value.raw_value
156159

157160
# Mongoid::RawValue skips any field-specific serialization logic
@@ -160,20 +163,18 @@ def evolve(serializer, value)
160163

161164
_value = case value
162165
when Hash
163-
evolve_hash(serializer, value)
166+
evolve_hash(serializer, value, is_raw_value)
164167
when Array
165-
evolve_array(serializer, value)
168+
evolve_array(serializer, value, is_raw_value)
166169
when Range
167-
value.__evolve_range__(serializer: serializer)
168-
when Mongoid::RawValue
169-
value
170+
evolve_range(serializer, value, is_raw_value)
170171
else
171172
(serializer || value.class).evolve(value)
172173
end
173174
_value
174175
end
175176

176-
# Evolve a single key selection with array values.
177+
# Evolve a single key selection with an array value.
177178
#
178179
# @api private
179180
#
@@ -182,15 +183,17 @@ def evolve(serializer, value)
182183
#
183184
# @param [ Object ] serializer The optional serializer for the field.
184185
# @param [ Array<Object> ] value The array to serialize.
186+
# @param [ Object ] is_raw_value Indicates that the evolve should be
187+
# processed as a member of a Mongoid::RawValue. Used for recursion.
185188
#
186189
# @return [ Object ] The serialized array.
187-
def evolve_array(serializer, value)
190+
def evolve_array(serializer, value, is_raw_value = false)
188191
value.map do |_value|
189-
evolve(serializer, _value)
192+
evolve(serializer, _value, is_raw_value)
190193
end
191194
end
192195

193-
# Evolve a single key selection with hash values.
196+
# Evolve a single key selection with a hash value.
194197
#
195198
# @api private
196199
#
@@ -199,19 +202,45 @@ def evolve_array(serializer, value)
199202
#
200203
# @param [ Object ] serializer The optional serializer for the field.
201204
# @param [ Hash ] value The hash to serialize.
205+
# @param [ Object ] is_raw_value Indicates that the evolve should be
206+
# processed as a member of a Mongoid::RawValue. Used for recursion.
202207
#
203208
# @return [ Object ] The serialized hash.
204-
def evolve_hash(serializer, value)
209+
def evolve_hash(serializer, value, is_raw_value = false)
205210
value.each_pair do |operator, _value|
206211
if operator =~ /exists|type|size/
207212
value[operator] = _value
208213
else
209-
value[operator] = evolve(serializer, _value)
214+
value[operator] = evolve(serializer, _value, is_raw_value)
210215
end
211216
end
212217
end
213218

214-
# Evolve a single key selection with range values. This method traverses
219+
# Evolve a single key selection with a range value.
220+
#
221+
# @api private
222+
#
223+
# @example Evolve a simple selection.
224+
# selector.evolve(field, (1..3))
225+
#
226+
# @param [ Object ] serializer The optional serializer for the field.
227+
# @param [ Range ] value The range to serialize.
228+
# @param [ Object ] is_raw_value Indicates that the evolve should be
229+
# processed as a member of a Mongoid::RawValue. Used for recursion.
230+
#
231+
# @return [ Hash ] The serialized range.
232+
def evolve_range(serializer, value, is_raw_value = false)
233+
if is_raw_value
234+
# (1..3) becomes { "min" => 1, "max" => 3 }
235+
value.mongoize
236+
else
237+
# (1..3) becomes { "$gte" => 1, "$lte" => 5 }
238+
value.__evolve_range__(serializer: serializer)
239+
end
240+
end
241+
242+
# Evolve a single key selection with range value at a top-level
243+
# node in a multi-list selection. This method traverses
215244
# the association tree to build a query for the given value and
216245
# serializer. There are three parts to the query here:
217246
#
@@ -239,12 +268,12 @@ def evolve_hash(serializer, value)
239268
#
240269
# @api private
241270
#
242-
# @param [ String ] key The to store the range for.
271+
# @param [ String ] key The key to store the range for.
243272
# @param [ Object ] serializer The optional serializer for the field.
244273
# @param [ Range ] value The Range to serialize.
245274
#
246275
# @return [ Array<String, Hash> ] The store name and serialized Range.
247-
def evolve_range(key, serializer, value)
276+
def evolve_top_level_range(key, serializer, value)
248277
v = value.__evolve_range__(serializer: serializer)
249278
assocs = []
250279
Fields.traverse_association_tree(key, serializers, associations, aliased_associations) do |meth, obj, is_field|

spec/mongoid/criteria/queryable/selector_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ def localized?
425425
end
426426

427427
it "serializes the raw_value" do
428-
expect(selector["key"]).to eq([{ foo: 1, "Bar" => [/baz/, BSON::Decimal128.new('2'), {"$gte"=>4, "$lte"=>5}] }, 3])
428+
expect(selector["key"]).to eq([{ foo: 1, "Bar" => [/baz/, BSON::Decimal128.new('2'), {"max"=>5, "min"=>4}] }, 3])
429429
end
430430
end
431431
end
@@ -672,7 +672,7 @@ def localized?
672672
end
673673

674674
it "serializes the raw_value" do
675-
expect(selector["key"]).to eq([{ foo: "1", "Bar" => [/baz/, BSON::Decimal128.new('2'), {"$gte"=>4, "$lte"=>5}] }, 3])
675+
expect(selector["key"]).to eq([{ foo: "1", "Bar" => [/baz/, BSON::Decimal128.new('2'), {"max"=>5, "min"=>4}] }, 3])
676676
end
677677
end
678678
end

0 commit comments

Comments
 (0)