Reputation: 2071
When I try to update an attribute on an embedded document (embeds_many), mongoid fails to save the changes, and curiously adds the changed attribute as a new attribute on the parent document instead. Here is a simple unit test that illustrates what I am trying to do:
class Tab
include Mongoid::Document
field :name, :type => String
embeds_many :components, :class_name => 'TabComponent'
end
class TabComponent
include Mongoid::Document
embeds_many :components, :class_name => "TabComponent"
end
class TabColumn < TabComponent
field :width, :type => Integer
end
require 'test_helper'
class TabTest < ActiveSupport::TestCase
test "create new tab" do
tab = Tab.new({
:name => "My Demo Tab",
:components => [TabColumn.new({
:width => 200
})]
})
tab.save!
tab.components[0].width = 300
tab.save!
assert_equal tab.components[0].width, 300 # passes
tab.reload
assert_equal tab.components[0].width, 300 # fails!
end
end
Here is the log output:
MONGODB (39ms) beam_test['system.namespaces'].find({})
MONGODB (27ms) beam_test['$cmd'].find({"count"=>"tabs", "query"=>{}, "fields"=>nil}).limit(-1)
MONGODB (38ms) beam_test['tabs'].find({})
MONGODB (0ms) beam_test['tabs'].remove({:_id=>BSON::ObjectId('4fb153c4c7597fbdac000002')})
MONGODB (0ms) beam_test['tabs'].insert([{"_id"=>BSON::ObjectId('4fb15404c7597fccb4000002'), "name"=>"My Demo Tab", "components"=>[{"_id"=>BSON::ObjectId('4fb15404c7597fccb4000001'), "_type"=>"TabColumn", "width"=>200}]}])
MONGODB (0ms) beam_test['tabs'].update({"_id"=>BSON::ObjectId('4fb15404c7597fccb4000002')}, {"$set"=>{"width"=>300}})
MONGODB (27ms) beam_test['tabs'].find({:_id=>BSON::ObjectId('4fb15404c7597fccb4000002')}).limit(-1)
Am I doing something wrong? Note that I don't think the problem is polymorphism, if I simplify things by putting width on TabComponent, the same behavior is observed.
Upvotes: 7
Views: 2661
Reputation: 3402
You have a simple error in your relation, instead use the following to complete the symmetry of your embeds_many / embedded-in relation.
class TabComponent
include Mongoid::Document
embedded_in :tab
end
In your log output above, you see:
MONGODB (0ms) beam_test['tabs'].update({"_id"=>BSON::ObjectId('4fb15404c7597fccb4000002')}, {"$set"=>{"width"=>300}})
After the above fix, I now get:
MONGODB (0ms) free11819_mongoid_embedded_update_test['tabs'].update({"_id"=>BSON::ObjectId('4fb270fee4d30bbc20000002')}, {"$set"=>{"components.0.width"=>300}})
Note the difference width
versus components.0.width
.
Hope that this helps to get you on your way.
Upvotes: 7