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

update_all does not map :as option of the field properly

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Critical - P2 Critical - P2
    • 9.0.0
    • Affects Version/s: None
    • Component/s: Persistence
    • None

      Scenario

      Supposed we have a simple model with as-optioned fields:

      class BuggyModel
        include ::Mongoid::Document
        store_in collection: 'buggy_models'  field :_a, as: :alfa, type: :integer, default: 1
        field :_b, as: :bravo, type: :integer, default: 1  # ignore the following field for now
        # it will be used in later arguments
        class CustomSerializer
          MAPPING = {
            'A' => 1,
            'B' => 2,
            'C' => 3,
          }.freeze    INVERSE_MAPPING = MAPPING.invert.freeze    class << self
            def mongoize(string)
              MAPPING[string]
            end      def demongoize(integer)
              INVERSE_MAPPING[integer]
            end      def evolve(string)
              mongoize(string)
            end
          end
        end
        field :charlie, type: CustomSerializer
      end 

      I created one document in the collection:

      BuggyModel.create!({ _id: 'test' }) 

      Then update the document:

      BuggyModel.where({ _id: 'test' }).update_all({ '$set': { alfa: 2 }, '$inc': { bravo: 1 } }) 

      What result do you expect from the following code?

      BuggyModel.find('test').then{ |d| [d.alfa, d.bravo] } 

      [2, 2]? like me?
      Nope, the current Mogoid returns [1, 1].

      Why?
      Because update_all does not map the field name with BuggyModel.aliased_fields properly.

      That's the problem.

      Supporting rationales

      You guys may argue that this is working as intended.
      Here is my argument against that hypothetical argument.

      Aliased fields work inside criteria:

      # this works
      BuggyModel.where({ alfa: 1 }).first 

      Fields with custom serializers work with update_all:

      # this works
      BuggyModel.where({ _id: 'test' }).update_all({ '$set': { charlie: 'B' } })
      # charlie field of the document will be set to 2 inside the database
      # and will be mapped to B properly outside the database. 

      I can't think of a plausible explanation why this should not work too:

      # this does not work
      BuggyModel.where({ _id: 'test' }).update_all({ '$set': { alfa: 2 } }) 

       

      What do you guys say?

       

       

            Assignee:
            jamis.buck@mongodb.com Jamis Buck
            Reporter:
            tom.selander@mongodb.com Tom Selander
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: