[dry-types] Coercing String with decimal to Integer fails

Using Types::Params::Integer to convert a String containing a number with a decimal point results in an error.
Dry::Types::Coercions::Params.to_int("1.5") = invalid value for Integer(): "1.5" (Dry::Types::CoercionError)

I assumed the converter would act identically to Ruby’s String#to_i and remove any digits after the decimal point.
"1.5".to_i = 1

Right now I’m adding a check before performing a call using Types::Params::Integer. If the value is a String, I use .to_i instead. But that feels like terrible hack. Can anyone suggest a better way?

It’s purposefully not acting as the built-in coercion as it’s not strict enough. You can define your own coercion like this:

irb(main):005:0> MyInt = Types.Constructor(Integer, &:to_i)
=> #<Dry::Types[Constructor<Nominal<Integer> fn=.to_i>]>
irb(main):006:0> MyInt["1.5"]
=> 1

However, notice that this may lead to all kinds of weird behavior, like this:

irb(main):008:0> MyInt["afa1.5afa"]
=> 0

This is why params coercions are much more strict about the input.

Ah, got it, that makes sense. Thank you for letting me know the right way to define my own coercion.

1 Like