mongoid.update_attributes fails on new embedded object

840 Views Asked by At

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.

1

There are 1 best solutions below

1
On

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