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

Strict option for fields to require successful and unambiguous type casts

    • Type: Icon: New Feature New Feature
    • Resolution: Unresolved
    • Priority: Icon: Unknown Unknown
    • None
    • Affects Version/s: None
    • Component/s: Attributes
    • None

      Background

      Mongoid permits applications to declare field types. For convenience, the field types (generally) permit assignment of a variety of values to the field, performing type conversions as necessary. For example, one can declare a field of type Integer and assign a string value (obtained from, for example, a web request) to it:

      class User
        include Mongoid::Document
        field :age, type: Integer
      end
      
      u = User.create!(age: "1")
      u.age # => 1
      

      This behavior can lead to data loss when the value conversion is lossy, which is quite common in Ruby. For example, `to_i` can cause the truncation of certain values:

      u = User.create!(age: "1.5")
      u.age # => 1
      

      Depending on the semantics of the field, the alteration can be meaningful.

      Ruby provides an alternative mechanism for converting strings to integers which validates that incoming values are converted without loss:

      irb(main):017:0> Integer('42')
      => 42
      irb(main):018:0> Integer('42foo')
      (irb):18:in `Integer': invalid value for Integer(): "42foo" (ArgumentError)
      irb(main):019:0> Integer('')
      (irb):19:in `Integer': invalid value for Integer(): "" (ArgumentError)
      

      Unfortunately, Mongoid presently does not make it easy to enforce a similar value validation for fields.

      Proposal

      This ticket is a feature request for adding a :strict option on the `field` macro.

      This option would cause assignments to this field to fail if the incoming value is not of the declared field type, and does not unambiguously convert to the declared field type:

      class User
        include Mongoid::Document
        field :age, type: Integer, strict: true
      end
      
      u = User.create!(age: "1.5")
      # raises InvalidValue error
      

      The expected usage of such a field would then be something like:

      u = User.create!(age: Integer(params[:age]))
      # raises an exception if params[:age] has anything other than a proper integer value
      

      The :strict option would default to false and raise an error if assigned without giving a type.

      In order to have the strict fields be practically useful, they would need to perform some type conversions, for example numeric promotions. They could also perform unambiguous value conversions across types, for example converting from "1" to 1.

      This ticket requires https://jira.mongodb.org/browse/MONGOID-5335 to be done first, for storing values in the declared field type and the associated custom field type protocol changes (typecast method).

            Assignee:
            Unassigned Unassigned
            Reporter:
            neil.shweky@mongodb.com Neil Shweky (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: