How to validate an array property itself and each item of array?

Hi everybody!

I’m new to dry-validation. I try to validate an incoming json which contains a property exclusion of type Array of String. I would like to validate that this property is (1) present and (2) its value is set and (3) of type of Array and (4) that this Array does not have an empty element.

In other words the following cases should be invalid:

{}                       # => incoming json doesn't have 'exclusion' key
{'exclusion': ''}          # => 'exclusion' key has empty value
{'exclusion': '2'}           # => 'exclusion' key has non-array value
{'exclusion': ['a', '']}    # => 'exclusion' array has empty item

So I tried to define this requirement in different way but none of them works (I use Dry::Validation.Form):

required(:exclusion) { filled? and (array? { each { filled? }}) }  
# => TypeError: no implicit conversion of Dry::Types::Definition into Hash

required(:exclusion) { (array? { each { filled? }}) and filled? } 
# => (array? { each { filled? }}) is not actually applied

required(:exclusion) { filled? & (array? { each { filled? }}) }  
# => TypeError: no implicit conversion of Dry::Types::Definition into Hash

required(:exclusion) { (array? { each { filled? }}) & filled? }
# => Uncaught exception: +&+ is not a valid predicate name

# I didn't see examples with macros chaining in the documentation 
# but for me it looks natural so I was expected that it should work
required(:exclusion).filled(:array?).each(:filled?)
# => .each(:filled?) is not actually applied

required(:exclusion).each(:filled?).filled(:array?)  
# => Uncaught exception: +filled+ is not a valid predicate name

# Since none of the above works I tried declare the property twice 
# with different requirements however it is conceptually wrong
required(:exclusion).each(:filled?)
required(:exclusion).filled(:array?)
# => .each(:filled?) is not actually applied

required(:exclusion).filled(:array?)
required(:exclusion).each(:filled?)
# => .filled(:array?) is actually applied

Could you help me, please, what is the correct way to declare this requirement?

This will work:

Dry::Validation.Form do
  required(:exclusion).value(min_size?: 1) { each(:filled?) }
end

Unfortunately chaining is not supported, and probably won’t be. I’m not sure yet how to make it nicer in cases like yours though. This is definitely something to address before 1.0.0.