Description
I'm attempting to port a custom validator to Grape v1.3.1:
requires :custom, type: ::API::Validations::Types::CustomObject, desc: 'This is a test'
At first, I tried to take https://github.com/ruby-grape/grape/blob/41ee988c06b87b036d12c4c7247d06b75bfa0b7f/lib/grape/validations/types/file.rb as an example:
module API
module Validations
module Types
class CustomObject
def coerce(input)
input
end
def coerced?(value)
value.is_a?(::CustomObject)
end
end
end
end
end
In Grape v1.1.0, this worked (ignore the coerced_value?
vs.coerced?
change and lack of inheritance of Virtus::Attribute
) because BuildCoercer.create_coercer_instance
would just fall through and create a Virtus Attribute: https://github.com/ruby-grape/grape/blob/v1.1.0/lib/grape/validations/types/build_coercer.rb#L71.
In Grape v1.3.1, with the switch to dry-types, all unknown types fall through to PrimitiveCoercer
and fails:
- .
- This quietly fails validation because
super
in eventually calls@coercer[val]
in . - This fails because
@coercer
isnil
.
To get around this, I saw the custom?
check appears to look for self.parse
:
grape/lib/grape/validations/types.rb
Lines 134 to 135 in 41ee988
module API
module Validations
module Types
class CustomObject
def self.coerce(input)
input
end
def self.coerced?(value)
value.is_a?(::CustomObject)
end
def self.parse(value)
value
end
end
end
end
end
This appears to work for my purposes, but it seems inconsistent (not to mention undocumented) compared to the built-in validators present in Grape.
Note that dry-types has a simple mechanism for checking types: https://dry-rb.org/gems/dry-types/master/custom-types. Ideally, we'd be able to pass in one of these custom types so we don't need all that code above, but this doesn't work either for the same reasons above:
requires :custom, type: DryTypes.Instance(Range), desc: 'This is a test'
@dnesteryuk My questions are:
- Should the Grape type validations look more consistent between
Json
,File
, and custom ones (e.g. class vs. instance methods,self.parse
method)? - If so, how can we make them more consistent? Otherwise, is this just a documentation issue?
- Should Grape handle custom dry-types (e.g. https://dry-rb.org/gems/dry-types/1.2/custom-types) natively?