Skip to content

Commit

Permalink
Merge pull request #113 from DiannaHohensee/MONGOID-3639
Browse files Browse the repository at this point in the history
MONGOID-3639 add merging of selectors with either '$nor' or '$nin' operators, rather than overwriting
  • Loading branch information
estolfo committed Nov 3, 2015
2 parents 3149ccf + 32fdd59 commit 8e8c31e
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 12 deletions.
24 changes: 21 additions & 3 deletions lib/origin/selector.rb
Expand Up @@ -18,7 +18,9 @@ class Selector < Smash
def merge!(other)
other.each_pair do |key, value|
if value.is_a?(Hash) && self[key.to_s].is_a?(Hash)
value = self[key.to_s].merge(value)
value = self[key.to_s].merge(value) do |_key, old_val, new_val|
multi_value?(_key) ? (old_val + new_val).uniq : new_val
end
end
if multi_selection?(key)
value = (self[key.to_s] || []).concat(value)
Expand Down Expand Up @@ -154,7 +156,7 @@ def evolve_hash(serializer, value)
end
end

# Determines if the selection is a multi-select, like an $and or $or
# Determines if the selection is a multi-select, like an $and or $or or $nor
# selection.
#
# @api private
Expand All @@ -168,7 +170,23 @@ def evolve_hash(serializer, value)
#
# @since 1.0.0
def multi_selection?(key)
key =~ /\$and|\$or/
key =~ /\$and|\$or|\$nor/
end

# Determines if the selection operator takes a list. Returns true for $in and $nin.
#
# @api private
#
# @example Does the selection operator take multiple values?
# selector.multi_value?("$nin")
#
# @param [ String ] key The key to check.
#
# @return [ true, false ] If the key is $in or $nin.
#
# @since 2.1.1
def multi_value?(key)
key =~ /\$nin|\$in/
end
end
end
18 changes: 9 additions & 9 deletions spec/origin/selectable_spec.rb
Expand Up @@ -2520,7 +2520,7 @@ def localized?

it "adds the $nor selector" do
expect(selection.selector).to eq({
"$nor" => [{ field: [ 1, 2 ] }]
"$nor" => [{"field" => [ 1, 2 ] }]
})
end

Expand All @@ -2540,8 +2540,8 @@ def localized?
it "adds the $nor selector" do
expect(selection.selector).to eq({
"$nor" => [
{ first: [ 1, 2 ] },
{ second: [ 3, 4 ] }
{ "first" => [ 1, 2 ] },
{ "second" => [ 3, 4 ] }
]
})
end
Expand All @@ -2560,8 +2560,8 @@ def localized?
it "appends both $nor expressions" do
expect(selection.selector).to eq({
"$nor" => [
{ first: [ 1, 2 ] },
{ first: [ 3, 4 ] }
{ "first" => [ 1, 2 ] },
{ "first" => [ 3, 4 ] }
]
})
end
Expand All @@ -2583,8 +2583,8 @@ def localized?
it "adds the $nor selectors" do
expect(selection.selector).to eq({
"$nor" => [
{ first: [ 1, 2 ] },
{ second: [ 3, 4 ] }
{ "first" => [ 1, 2 ] },
{ "second" => [ 3, 4 ] }
]
})
end
Expand All @@ -2603,8 +2603,8 @@ def localized?
it "appends both $nor expressions" do
expect(selection.selector).to eq({
"$nor" => [
{ first: [ 1, 2 ] },
{ first: [ 3, 4 ] }
{ "first" => [ 1, 2 ] },
{ "first" => [ 3, 4 ] }
]
})
end
Expand Down
56 changes: 56 additions & 0 deletions spec/origin/selector_spec.rb
Expand Up @@ -42,6 +42,34 @@
end
end

context "when selector contains a $nin" do

let(:initial) do
{ "$nin" => ["foo"] }
end

before do
selector["field"] = initial
end

context "when merging in a new $nin" do

let(:other) do
{ "field" => { "$nin" => ["bar"] } }
end

before do
selector.merge!(other)
end

it "combines the two $nin queries into one" do
expect(selector).to eq({
"field" => { "$nin" => ["foo", "bar"] }
})
end
end
end

context "when selector is not nested" do

before do
Expand Down Expand Up @@ -117,6 +145,34 @@
end
end
end

context "when the selector contains a $nor" do

let(:initial) do
[{ "value" => 1 }]
end

before do
selector["$nor"] = initial
end

context "when merging in a new $nor" do

let(:other) do
[{ "value" => 2 }]
end

before do
selector.merge!({ "$nor" => other })
end

it "combines the two $nor queries into one" do
expect(selector).to eq({
"$nor" => initial + other
})
end
end
end
end

describe "#__deep_copy__" do
Expand Down

0 comments on commit 8e8c31e

Please sign in to comment.