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

Demongoize not called when using read_attribute for custom type

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 7.0.0
    • Affects Version/s: 6.2.1
    • Component/s: None
    • None
    • Environment:
      MacOS, Ruby 2.3.5

      Re-using the custom type example from the documentation.

      class Point
      
        attr_reader :x, :y
      
        def initialize(x, y)
          @x, @y= x, y
        end
      
        # Converts an object of this instance into a database friendly value.
        def mongoize
          [ x, y ]
        end
      
        class << self
      
          # Get the object as it was stored in the database, and instantiate
          # this custom class from it.
          def demongoize(object)
            Point.new(object[0], object[1])
          end
      
          # Takes any possible object and converts it to how it would be
          # stored in the database.
          def mongoize(object)
            case object
              when Point then object.mongoize
              when Hash then Point.new(object[:x], object[:y]).mongoize
              else object
            end
          end
      
          # Converts the object that was supplied to a criteria and converts it
          # into a database friendly form.
          def evolve(object)
            case object
              when Point then object.mongoize
              else object
            end
          end
        end
      end
      
      class Profile
        include Mongoid::Document
        field :location, type: Point
      end
      

      This piece of verification code:

      Profile.create!(location: Point.new(10, 20))
      profile = Profile.first
      puts profile[:location].class
      puts profile.read_attribute(:location).class
      puts profile.location.class
      

      Outputs:

      {{Array
      Array
      Point}}

      As you can see demongoization using the custom type class is only performed when using the field getter (profile.location). The other access methods skips demongoization and returns whatever type is stored in the database.

      To me this is broken. Nothing says that the access method of a field affects de-serialization of a value. When creating a custom type, it's a huge risk. It might cause loss of/corrupt data.

            Assignee:
            emily.stolfo Emily Stolfo
            Reporter:
            carl.vander@valtech.se Carl Vander
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: