How to define a message template for array indices efficiently

Hi, how do I set a message template for array indices efficiently in dry-schema and dry-validation? For example, I have the following schema definition to get the result like the second code block. The error messages are in English here for simplicity though another language in the actual use case.

params do
  required(:ages).value(:array).each(:integer)
  required(:images).value(:array).each(type?: ActionDispatch::Http::UploadedFile)
end
Validator.new.call(params).errors(full: true).to_h
#=>
# {
#   ages: { 1: ["element 1 should be an integer"] },
#   images: { 1: ["image 1 should be an image"] }
# }

I believe it’s possible to define a YAML file like the below:

dry-validation:
  rules:
    1: element 1
    2: element 2
    ...
    foo:
      rules
        1: image 1
        2: image 2
        ...
  errors:
    int?: should be an integer
    foo:
      rules:
        images:
          type?: should be an image

but it’s painful to set a message for each index and I’m not sure how many elements the arrays have. It would be DRY and ideal to be able to define like:

dry-validation:
  rules:
    array:
      index: "element %{index}"
    foo:
      array:
        index: "image %{index}"

Any way to do like this in dry-schema and dry-validation or should I implement it myself?

If you’re after nice messages I suggest using a rule block for the whole array:

params do
  required(:ages).value(:array)
end

rule(:ages) do
  value.each_with_index do |el, idx|
    key.failure("element #{idx} must be an integer") unless el.is_a?(::Integer)
  end
end
1 Like

OK, so I should validate elements in rule block instead of params block. The problem is, I can coerce the elements in that case though. Thank you!