I try to create a new embedded object with update_attributes from its parent. In mongoid 2.0.0.beta20 this worked fine, but after updating to 2.3.3, this fails.
To reproduce, you can use this model structure:
class Bird
include Mongoid::Document
embeds_one :egg
accepts_nested_attributes_for :egg
end
class Egg
include Mongoid::Document
field :weight, :type => Integer, :default => 10
field :size, :type => Array, :default => [10,10]
def height=(value)
self.size[0] = value
end
def width=(value)
self.size[1] = value
end
def height
self.size[0]
end
def width
self.size[1]
end
end
Then, run in the ruby console:
b = Bird.new
=> #<Bird _id: 4eb163660d996a3e43000002, _type: nil>
b.update_attributes "egg" => { "height" => 20, "weight" => 20 }
NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]=
from (irb):14:in `height='
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/attributes/processing.rb:98:in `process_attribute'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/attributes/processing.rb:26:in `block in process'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/attributes/processing.rb:24:in `each_pair'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/attributes/processing.rb:24:in `process'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/document.rb:131:in `block in initialize'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/threaded/lifecycle.rb:84:in `_building'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/document.rb:127:in `initialize'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/factory.rb:23:in `new'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/factory.rb:23:in `build'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/relations/builders/nested_attributes/one.rb:30:in `build'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/attributes/processing.rb:137:in `block in process_relations'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/attributes/processing.rb:134:in `each_pair'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/attributes/processing.rb:134:in `process_relations'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/attributes/processing.rb:122:in `process_pending'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/attributes/processing.rb:29:in `process'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/attributes.rb:133:in `block in assign_attributes'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/threaded/lifecycle.rb:26:in `_assigning'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/attributes.rb:132:in `assign_attributes'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/attributes.rb:154:in `write_attributes'
from vendor/ruby/1.9.1/gems/mongoid-2.3.3/lib/mongoid/persistence.rb:115:in `update_attributes'
from (irb):36
from vendor/ruby/1.9.1/gems/railties-3.1.1/lib/rails/commands/console.rb:45:in `start'
from vendor/ruby/1.9.1/gems/railties-3.1.1/lib/rails/commands/console.rb:8:in `start'
from vendor/ruby/1.9.1/gems/railties-3.1.1/lib/rails/commands.rb:40:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'system :037 >
This is because the embedded object does not get initialized before the new values are set. That's why the size array is not initialized and is therefore still nil. Using mongoid-2.0.0.beta20 (from which I upgrade), all works fine. Is there something I miss? Does the new mongo-2.3.3 expect ME to initialize the embedded object first!?
Thanks for any help|hint.
Defaults are now applied after all the other attributes are being set, in case you were to use a proc as the default that conditionally depended on the others. Your height= and width= methods need to be aware of this now.
See:
https://github.com/mongoid/mongoid/issues/1075