-
Type: Task
-
Resolution: Done
-
Affects Version/s: None
-
Component/s: None
Hi,
I've got a strange behavior on 2 levels nested attributes with mongoid-3.0.5 (forms are handled by simple_form and cocoon).
I have 3 models : Node, Volume and Filesystem.
Node has_many :volumes and Volume embeds_many :filesystems.
When adding new filesystems to an existing volume, those filesystems are persisted twice, with the same ID.
When destroying one of those filesystems, both are destroyed (since they have the same id).
The problem does not occurs when :
_ Adding filesystems on a _new* volume (both created on the same time)
- Using Volume has_many :filesystems instead of Volume embeds_many :filesystems (+ belongs_to instead of embedded_in in Filesystem)
Code samples :
(I just skip validations, which are just presence, inclusion and numericality, and custom instance methods)
volume.rb header :
class Volume # INCLUSIONS include Mongoid::Document include Mongoid::Timestamps # RELATIONS belongs_to :node embeds_many :filesystems accepts_nested_attributes_for :filesystems, allow_destroy: true, reject_if: proc { |attributes| attributes.all? {|k,v| v.blank? || ['size_unit'].include?(k)} } # FIELDS field :name field :size field :size_unit, default: :gb [...]
filesystem.rb header :
class Filesystem # INCLUSIONS include Mongoid::Document include Mongoid::Timestamps # RELATIONS embedded_in :volume # FIELDS field :mount_point field :name field :size field :size_unit, default: :gb [...]
nodes_controller.rb update method :
def update @node= platform.nodes.find_by name: params[:id] if @node.update_attributes params[:node] flash[:success] = t_flash :update_success, @node redirect_to platforms_platform_node_path(organization, platform, @node) else flash.now[:error] = t_flash :update_error, @node, count: @node.errors.count render :form end end
params hash :
(I only paste params[:node][:volume_attributes] part since Node has many other nested attributes)
When creating a new Volume with a Filesystem :
volumes_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess '0': !ruby/hash:ActiveSupport::HashWithIndifferentAccess name: rootvg size: '100' size_unit: gb filesystems_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess '0': !ruby/hash:ActiveSupport::HashWithIndifferentAccess mount_point: / name: rootlv size: '10' size_unit: gb
Gives :
irb(main):004:0> Node.find_by(name: 'Server1').volumes.first.filesystems.each{|f| puts f.inspect} #<Filesystem _id: 503f78226fad9df0220000f2, _type: nil, created_at: nil, updated_at: nil, mount_point: "/", name: "rootlv", size: "10", size_unit: "gb">
When adding a new Filesystem to the same Volume :
volumes_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess '0': !ruby/hash:ActiveSupport::HashWithIndifferentAccess name: rootvg size: '100' size_unit: gb filesystems_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess '0': !ruby/hash:ActiveSupport::HashWithIndifferentAccess mount_point: / name: rootlv size: '10' size_unit: gb '1346337168506': !ruby/hash:ActiveSupport::HashWithIndifferentAccess mount_point: /home name: homelv size: '20' size_unit: gb
(Volume and first Filesystem IDs do not appear here since it's the filtered params hash but they are sent in the post request)
Gives :
irb(main):008:0> Node.find_by(name: 'Server1').volumes.first.filesystems.each{|f| puts f.inspect} #<Filesystem _id: 503f78226fad9df0220000f2, _type: nil, created_at: nil, updated_at: nil, mount_point: "/", name: "rootlv", size: "10", size_unit: "gb"> #<Filesystem _id: 503f79a16fad9df0220000fa, _type: nil, created_at: nil, updated_at: nil, mount_point: "/home", name: "homelv", size: "20", size_unit: "gb"> #<Filesystem _id: 503f79a16fad9df0220000fa, _type: nil, created_at: nil, updated_at: nil, mount_point: "/home", name: "homelv", size: "20", size_unit: "gb">
Note : I've just noted when pasting this log that filesystems timestamps fields are created with nil value...which is not the case of the Volume :
`irb(main):024:0> Node.find_by(name: 'Server1').volumes.first => #<Volume _id: 503f78226fad9df0220000ef, _type: nil, created_at: 2012-08-30 14:26:42 UTC, updated_at: 2012-08-30 14:37:03 UTC, node_id: "503f78066fad9df0220000e9", name: "rootvg", size: "100", size_unit: "gb">