Uploaded image for project: 'Mongoid'
  1. Mongoid
  2. MONGOID-2989

Conflicting or missing modifications when updating using nested attributes

    • Type: Icon: Task Task
    • Resolution: Won't Fix
    • Priority: Icon: Major - P3 Major - P3
    • 12_01_17
    • Affects Version/s: None
    • Component/s: None
    • Labels:

      Summary

      Given a root document embedding two or more levels of documents, updating the embedded documents via mass-assignment and nested attributes can cause a conflicting modifications exception or persist the modifications under a blank key.

      Steps to reproduce

      Given the following documents:

      class Train
        include Mongoid::Document
        
        embeds_many :cars
        
        accepts_nested_attributes_for :cars
      end
      
      # A train car
      class Car
        include Mongoid::Document
        
        embedded_in :train
        embeds_many :seats
          
        def capacity=(count)
          self.seats = Array.new(count).map { Seat.new }
        end
      end
      
      class Seat
        include Mongoid::Document
        
        embedded_in :car
      end
      

      Execute:

      t = Train.create!
      t.update_attributes(cars_attributes: [{capacity: 2}])
      

      Expected results

      A train is persisted with one car containing two seats. The document is stored in Mongo as:

      {
      	"_id" : ObjectId("51746559e3defe7883000001"),
      	"cars" : [
      		{
      			"_id" : ObjectId("51746559e3defe7883000002"),
      			"seats" : [
      				{
      					"_id" : ObjectId("51746559e3defe7883000003")
      				},
      				{
      					"_id" : ObjectId("51746559e3defe7883000004")
      				}
      			]
      		}
      	]
      }
      

      Actual results

      If using Mongo 2.0.4 the update will fail with a conflicting-mods error from Mongo. The car and its seats will not be created.

      If using Mongo 2.4.2 the update will appear to succeed. Upon reloading the train, however, it will have no cars and no seats. The document is stored in Mongo as:

      {
      	"" : [
      		{
      			"_id" : ObjectId("51745e08e3defeea70000004"),
      			"seats" : [
      				{
      					"_id" : ObjectId("51745e08e3defeea70000002")
      				},
      				{
      					"_id" : ObjectId("51745e08e3defeea70000003")
      				}
      			]
      		}
      	],
      	"_id" : ObjectId("51745e04e3defeea70000001"),
      	"seats" : [
      		{
      			"_id" : ObjectId("51745e08e3defeea70000002")
      		},
      		{
      			"_id" : ObjectId("51745e08e3defeea70000003")
      		}
      	]
      }
      

      Configuration used

      • Rails 3.2.13
      • Mongoid 3.1.3
      • Safe mode enabled for Mongoid session
      • Mongo 2.0.4 when producing the conflicting-mods behavior
      • Mongo 2.4.2 when producing the missing modifications behavior

      Attachments

            Assignee:
            durran.jordan@mongodb.com Durran Jordan
            Reporter:
            evanchaney evanchaney
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: