-
Type: New Feature
-
Resolution: Unresolved
-
Priority: 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).