Skip to content

Commit

Permalink
MONGOID-5686 Fix array operations in update_all (#5726)
Browse files Browse the repository at this point in the history
  • Loading branch information
comandeo-mongo authored Sep 29, 2023
1 parent 34f7a91 commit 8c79f57
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 7 deletions.
20 changes: 19 additions & 1 deletion lib/mongoid/extensions/hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def __consolidate__(klass)
real_key = klass.database_field_name(key2)

value.delete(key2) if real_key != key2
value[real_key] = (key == "$rename") ? value2.to_s : mongoize_for(key, klass, real_key, value2)
value[real_key] = value_for(key, klass, real_key, value2)
end
consolidated[key] ||= {}
consolidated[key].update(value)
Expand Down Expand Up @@ -166,6 +166,24 @@ def to_criteria

private

# Get the value for the provided operator, klass, key and value.
#
# This is necessary for special cases like $rename, $addToSet and $push.
#
# @param [ String ] operator The operator.
# @param [ Class ] klass The model class.
# @param [ String | Symbol ] key The field key.
# @param [ Object ] value The original value.
#
# @return [ Object ] Value prepared for the provided operator.
def value_for(operator, klass, key, value)
case operator
when "$rename" then value.to_s
when "$addToSet", "$push" then value.mongoize
else mongoize_for(operator, klass, operator, value)
end
end

# Mongoize for the klass, key and value.
#
# @api private
Expand Down
47 changes: 41 additions & 6 deletions spec/mongoid/contextual/mongo_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3608,16 +3608,51 @@

context "when the attributes are in the correct type" do

before do
context.update_all("$set" => { name: "Smiths" })
context "when operation is $set" do

before do
context.update_all("$set" => { name: "Smiths" })
end

it "updates the first matching document" do
expect(depeche_mode.reload.name).to eq("Smiths")
end

it "updates the last matching document" do
expect(new_order.reload.name).to eq("Smiths")
end
end

it "updates the first matching document" do
expect(depeche_mode.reload.name).to eq("Smiths")
context "when operation is $push" do

before do
depeche_mode.update_attribute(:genres, ["electronic"])
new_order.update_attribute(:genres, ["electronic"])
context.update_all("$push" => { genres: "pop" })
end

it "updates the first matching document" do
expect(depeche_mode.reload.genres).to eq(["electronic", "pop"])
end

it "updates the last matching document" do
expect(new_order.reload.genres).to eq(["electronic", "pop"])
end
end

it "updates the last matching document" do
expect(new_order.reload.name).to eq("Smiths")
context "when operation is $addToSet" do

before do
context.update_all("$addToSet" => { genres: "electronic" })
end

it "updates the first matching document" do
expect(depeche_mode.reload.genres).to eq(["electronic"])
end

it "updates the last matching document" do
expect(new_order.reload.genres).to eq(["electronic"])
end
end
end

Expand Down

0 comments on commit 8c79f57

Please sign in to comment.