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

Potential for objects not being persisted when written using subscript operator

    • Type: Icon: Bug Bug
    • Resolution: Duplicate
    • Priority: Icon: Minor - P4 Minor - P4
    • None
    • Affects Version/s: 7.0.1
    • Component/s: Associations, Persistence
    • None

      This may be a duplicate/related to MONGOID-4683, but I think it is different because this depends on how the field is accessed. I have found this in hash fields (but I'm sure it could be reproduce in other fields too).

      Here is an example model:

      class SomeHashModel
        include Mongoid::Document
        field :some_hash, type: Hash
      end
      

      If I reference the field using `[:some_hash]` I get the following results.

      
      something = SomeHashModel.create(some_hash:{key1: 'value1'})
      something[:some_hash].merge!(key2: 'value2')
      # or something[:some_hash][:key2] = 'value2'
      something.save!
      something.some_hash # => {key1: 'value1', key2: 'value2'}
      something.reload
      something.some_hash # => {key1: 'value1'}
      
      

      If I reference the field using `.some_hash` sometime before I change the object I get the following results.

      something = SomeHashModel.create(some_hash: {key1: 'value1'})
      something.some_hash
      something[:some_hash].merge!(key2: 'value2')
      # or something[:some_hash][:key2] = 'value2'
      something.save!
      something.some_hash # => {key1: 'value1', key2: 'value2'}
      something.reload
      something.some_hash # => {key1: 'value1', key2: 'value2'}
      
      

      I have also noticed that if it is a string, it doesn't seem to depend on how I reference the field. Here is an example:

      class SomeStringModel
        include Mongoid::Document
      
        field :some_string, type: String
      end
      
      
      something_created = SomeStringModel.create(some_string: 'value1')
      # This line below is only needed if you have '# frozen_string_literal: true'
      something = SomeStringModel.find(something_created.id)
      # or something.some_hash
      something[:some_string].prepend('something_super_cool_')
      something.save!
      something.some_string # => 'something_super_cool_value1'
      something.reload
      something.some_string # => 'value1'
      
      

            Assignee:
            neil.shweky@mongodb.com Neil Shweky (Inactive)
            Reporter:
            jonathongardner Jonathon Gardner
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: