-
Type: Bug
-
Resolution: Fixed
-
Priority: Major - P3
-
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.