There seems to be a small discrepancy in how constructors work. My schema always gets arrays as values, even if they have only one element. In some cases I want to grab the first element of an array and coerce it to a type. In any case the type I’m using to extract the first element from an array as a stringified bool looks like this Types::Params::Bool.constructor(&:first) and works just fine:
[21] pry(main)> Types::Params::Bool.constructor(&:first).call(['false'])
=> false
[22] pry(main)> Types::Params::Bool.constructor(&:first).call(['ffalse'])
Dry::Types::CoercionError: ffalse cannot be coerced to false
However the same thing with date doesn’t work:
[20] pry(main)> Types::Params::Date.constructor(&:first).call(['2019-01-05'])
Dry::Types::CoercionError: ["2019-01-05"] is not a string
from /usr/local/bundle/gems/dry-types-1.2.2/lib/dry/types/coercions.rb:47:in `to_date'
@DawidJanczak this is expected although I’m not suprised it confused you - Types::Params::*are constructor types, so their coercion logic is applied before yours. This means you need to prepend your logic:
Thank you @solnic, that works! Piggybacking on that how do I handle invalid dates in those situations? Suppose I use the type you defined above in a params block in a schema like so:
when provided with invalid date the schema fails with Dry::Types::CoercionError: invalid date on an input like date: %w[2019-08-FO]. Should I be handling that myself with the mechanism described here https://github.com/dry-rb/dry-types/blob/master/CHANGELOG.md#added-4 or is there another way to approach this?
Also I tried to do the same for Bool (Types::Params::Bool.prepend(&:first)) and that fails with undefined method prepend’ for #Dry::Types::Sum:0x000055aa4531d630` Perhaps that’s where the discrepancy is coming from?
Similar thing happens with String: Types::String.prepend(&:first) throws `undefined method prepend' for #<Dry::Types[Constrained<Nominal<String> rule=[type?(String)]>]>