Using assign_attributes with nested attributes on has_many model erroneously persists

XMLWordPrintableJSON

    • Type: Bug
    • Resolution: Unresolved
    • Priority: Major - P3
    • None
    • Affects Version/s: None
    • Component/s: None
    • None
    • None
    • Ruby Drivers
    • None
    • None
    • None
    • None
    • None
    • None

      Have a model that includes has_many association and embeds_many association. Using accepts_nested_attributes_for on each of them. When using parent.assign_attributes, the has_many changes are being persisted, not just assigned. Embedded is working as expected.

      Note the follow reproduction. post.assign_attributes is used. Reloading the comment and embdded_comment after using assign_attributes and comparing titles shows that the embedded comment title was not persisted (as expected), but the has_many comment got saved to the DB. assign_attributes should not do this.

      require 'bundler/inline'
      
      gemfile do
        source 'https://rubygems.org'
        gem 'mongoid', '9.0.8'
      end
      
      Mongoid.configure do |config|
        config.clients.default = {
          hosts: ['localhost:27017'],
          database: 'mongoid_test',
        }
      end
      
      class Post
        include Mongoid::Document
      
        has_many :comments, inverse_of: :post
        embeds_many :embedded_comments, inverse_of: :post
      
        accepts_nested_attributes_for :comments, allow_destroy: true
        accepts_nested_attributes_for :embedded_comments, allow_destroy: true
      
        field :title, type: String
      end
      
      class Comment
        include Mongoid::Document
      
        belongs_to :post, inverse_of: :comments
      
        field :title, type: String
      end
      
      class EmbeddedComment
        include Mongoid::Document
      
        embedded_in :post, inverse_of: :embedded_comments
      
        field :title, type: String
      end
      
      post = Post.create(title: 'Post')
      comment = post.comments.create(title: 'Comment')
      embedded_comment = post.embedded_comments.create(title: 'Embedded Comment')
      
      puts 'Before:'
      puts comment.reload.title
      puts embedded_comment.reload.title
      puts ''
      
      post.assign_attributes(
        comments_attributes: [
          {
            _id: comment.id,
            title: 'Edited Comment',
          },
        ],
        embedded_comments_attributes: [
          {
            _id: embedded_comment.id,
            title: 'Edited Embedded Comment',
          },
        ],
      )
      
      puts 'After:'
      puts comment.reload.title
      puts embedded_comment.reload.title
      puts ''
      

            Assignee:
            Unassigned
            Reporter:
            Kieran Pilkington
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: