Array of hashes on a custom type in params schema

Hello!

I was wondering if it’s possible to make array of hashes work as a nested schema while using a custom type constraining the array.

Assuming the following input: { array: [ { key_1: '1', key_2: '2' }, { key_2: '3' }] } and a custom type filtering members of the array that do not have key_1 present FilterArray = Types.Constructor(Types::Array) { |arr| arr.select { |h| h[:key_1] } } I’d like to work with a params schema like this:

params do
  required(:array).value(FilterArray).each do
    hash do
      required(:key_1).filled(:integer)
      required(:key_2).filled(:integer)
    end
  end
end

so that the second member of the array gets rejected before we hit the validation.

The above is working fine with one exception: the keys inside the hash are not automatically coerced to ints and so the validation fails with incorrect type despite it being params one. When I substitute FilterArray with just Types::Array it works fine.

This is quite complicated so let me know if something’s unclear and/or if there’s a better way to go about it :slight_smile:

Try either Types.Constructor(::Array) or Types::Array.constructor instead

Brilliant, thank you @flash-gordon! The first one doesn’t work (fails with Cannot define schema for a nominal array type. Array types must be instances of Dry::Types::Array(...)), but the other one works great.

Just out of curiosity what’s the difference between Types.Constructor(Types::Array) and Types::Array.constructor?

Not sure, but this is probably related https://github.com/dry-rb/dry-types/blob/master/CHANGELOG.md#fixed

1 Like