-
Type: Task
-
Resolution: Done
-
Affects Version/s: None
-
Component/s: None
I found an issue with remove_attribute called on newly created embedded documents. Seems like mongoid doesn't notice it's a new document and generates an $unset command, but completely messes the path to the document (since it doesn't have a position in an array of children yet). If the child document was persisted it would generate {{"$unset"=>
{"child_documents.X.flag"=>true}}} command, where X would be the position of updated child document. On a new document it generates {{"$unset"=>
{"child_documents.flag"=>true}}} command and MongoDB silently rejects the whole update operation along with any other changes that were included.I think remove_attribute should check new_document? before generating $unset operation.
Here's a script to replicate the bug:
#!/usr/bin/env ruby require 'mongoid' Mongoid.configure do |config| config.connect_to "mongoid_test" end Moped.logger = Logger.new(STDOUT) class RootDocument include Mongoid::Document embeds_many :child_documents end class ChildDocument include Mongoid::Document embedded_in :root_document field :flag, type: Boolean end RootDocument.delete_all parent = RootDocument.create child1 = parent.child_documents.build child1.flag = true parent.save! puts "Root document: " + RootDocument.first.as_json.inspect child2 = parent.child_documents.build child2.remove_attribute :flag parent.save! # this update is silently rejected by MongoDB puts "Root document: " + RootDocument.first.as_json.inspect
And here's the output with some lines removed for clarity:
MOPED: 127.0.0.1:27017 INSERT database=mongoid_test collection=root_documents documents=[{"_id"=>"513ab4b066d9f181f0000001"}] flags=[] (0.1130ms)
MOPED: 127.0.0.1:27017 UPDATE database=mongoid_test collection=root_documents selector={"_id"=>"513ab4b066d9f181f0000001"} update={"$pushAll"=>{"child_documents"=>[{"_id"=>"513ab4b066d9f181f0000002", "flag"=>true}]}} flags=[] (0.1299ms)
Root document: {"_id"=>"513ab4b066d9f181f0000001", "child_documents"=>[{"_id"=>"513ab4b066d9f181f0000002", "flag"=>true}]}
MOPED: 127.0.0.1:27017 UPDATE database=mongoid_test collection=root_documents selector={"_id"=>"513ab4b066d9f181f0000001"} update={"$unset"=>{"child_documents.flag"=>true}
, "$pushAll"=>{"child_documents"=>[
{"_id"=>"513ab4b066d9f181f0000003"}]}} flags=[] (0.0951ms)
Root document: {"_id"=>"513ab4b066d9f181f0000001", "child_documents"=>[
]}