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

accept_nested_attributes doesn't work for multiple levels

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Minor - P4 Minor - P4
    • None
    • Affects Version/s: 4.0.0 final, 5.0.2
    • Component/s: Associations, Attributes
    • Labels:
      None

      Models
      class Author
        include Mongoid::Document
      
        field :name, type: String
        has_one :post
        accepts_nested_attributes_for :post
      end
      
      class Comment
        include Mongoid::Document
      
        field :body, type: String
        belongs_to :post
      end
      
      class Post
        include Mongoid::Document
      
        field :title, type: String
        belongs_to :author
        has_many :comments
        accepts_nested_attributes_for :comments
      end
      
      Spec
      require 'rails_helper'
      
      RSpec.describe Comment, type: :model do
        describe "accepts_nested_attributes relationships" do
          let(:author) { Author.create }
          let(:one_level_params) { { post_attributes: { title: 'test' } } }
          let(:two_levels_params) { { post_attributes: { comments_attributes: [ { body: 'test' } ] } } }
      
          it "creates a 1st-depth child model" do
            author.update_attributes(one_level_params)
            author.post.persisted?.should eq(true)
          end
      
          it "creates a 1st-depth child model, and a 2nd-depth child model" do
            author.update_attributes(two_levels_params)
            author.post.comments.count.should eq(1)
          end
      
          context "the 1st-depth child model already exists" do
            it "creates a 2nd-depth child model" do
              author.create_post(title: 'test') # Assume the first nested child relationship exists
              author.update_attributes(two_levels_params)
              author.post.comments.count.should eq(1) # This fails
            end
          end
        end
      end
      

      As you can see by the example above, this issue affects deeply nested accepts_nested_attributes_for use cases. In other words, using accepts_nested_attributes recursively.

      In the example of a data model of Author -> Post -> Comments, submitting the following hash to

      update_attributes

      will fail to save the appropriate the 2nd-depth Comments model:

      author.update_attributes({post_attributes: { 
          comments_attributes: [ 
              { body: 'test' }
          ]
      })

      If the 1st-depth Post model does not exist, the same call will save the 2nd-depth Comments model. The example spec above includes both of these cases. My assumption is that submitting deeply nested attributes, without otherwise mutating the first layer nested attributes (i.e. Post in this example), will not mark the 1st depth model as being dirty - and those will not propagate the autosave to the 2nd depth model.

      The above spec does pass using ActiveRecord 4.x (and making the appropriate changes to the models above), and in Mongoid 3.x, so this is a regression.

            Assignee:
            neil.shweky@mongodb.com Neil Shweky (Inactive)
            Reporter:
            jdjkelly_ Joshua Kelly
            Votes:
            2 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: