Skip to content

Commit 626a9ba

Browse files
authored
MONGOID-5642 Queryable::Selector#merge! does not properly handle :$in/:$nin keys (#5655)
* Change Mongoid::Criteria::Queryable::Selector#merge! to correctly merge $in and $nin when provided as a symbol as well as a string * Mongoid::Criteria::Queryable::Selector#merge! convert to strings before matching * cleanup whitespace
1 parent 503fba5 commit 626a9ba

File tree

2 files changed

+76
-3
lines changed

2 files changed

+76
-3
lines changed

lib/mongoid/criteria/queryable/selector.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def merge!(other)
2121
other.each_pair do |key, value|
2222
if value.is_a?(Hash) && self[key.to_s].is_a?(Hash)
2323
value = self[key.to_s].merge(value) do |_key, old_val, new_val|
24-
case _key
24+
case _key.to_s
2525
when '$in'
2626
new_val & old_val
2727
when '$nin'

spec/mongoid/criteria/queryable/selector_spec.rb

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
end
4646
end
4747

48-
context "when selector contains a $nin" do
48+
context "when selector contains a $nin string" do
4949

5050
let(:initial) do
5151
{ "$nin" => ["foo"] }
@@ -73,7 +73,35 @@
7373
end
7474
end
7575

76-
context "when selector contains a $in" do
76+
context "when selector contains a $nin symbol" do
77+
78+
let(:initial) do
79+
{ :$nin => ["foo"] }
80+
end
81+
82+
before do
83+
selector["field"] = initial
84+
end
85+
86+
context "when merging in a new $nin" do
87+
88+
let(:other) do
89+
{ "field" => { :$nin => ["bar"] } }
90+
end
91+
92+
before do
93+
selector.merge!(other)
94+
end
95+
96+
it "combines the two $nin queries into one" do
97+
expect(selector).to eq({
98+
"field" => { :$nin => ["foo", "bar"] }
99+
})
100+
end
101+
end
102+
end
103+
104+
context "when selector contains a $in string" do
77105

78106
let(:initial) do
79107
{ "$in" => [1, 2] }
@@ -118,6 +146,51 @@
118146
end
119147
end
120148

149+
context "when selector contains a $in symbol" do
150+
151+
let(:initial) do
152+
{ :$in => [1, 2] }
153+
end
154+
155+
before do
156+
selector["field"] = initial
157+
end
158+
159+
context "when merging in a new $in with an intersecting value" do
160+
161+
let(:other) do
162+
{ "field" => { :$in => [1] } }
163+
end
164+
165+
before do
166+
selector.merge!(other)
167+
end
168+
169+
it "intersects the $in values" do
170+
expect(selector).to eq({
171+
"field" => { :$in => [1] }
172+
})
173+
end
174+
end
175+
176+
context "when merging in a new $in with no intersecting values" do
177+
178+
let(:other) do
179+
{ "field" => { :$in => [3] } }
180+
end
181+
182+
before do
183+
selector.merge!(other)
184+
end
185+
186+
it "intersects the $in values" do
187+
expect(selector).to eq({
188+
"field" => { :$in => [] }
189+
})
190+
end
191+
end
192+
end
193+
121194
context "when selector is not nested" do
122195

123196
before do

0 commit comments

Comments
 (0)