I have a data structure that I am trying to validate where it is required that there be an array of items, and each array entry is a hash containing structured data of the item. The problem is that the errors returned from validation might be an array of strings if the items array isn’t present, or doesn’t contain any elements, or it might be an array of hashes where each element corresponds to that element in the items array.
It’s not the end of the world or anything, it just seems odd that sometimes I might have {items: ['is missing']} and other times {items:[{amount: ['is missing']}, {amount: ['is missing']}]}. I should also note that I really don’t know what a better way to do this would be in terms of returning the errors to the user short of making the complicated object structure for nested errors.
validation do
required(:items).value(type?: Array, min_size?: 1) do
each do
schema do
required(:amount).filled(:int?)
end
end
end
end
Do you have an idea how we could make this structure better? I’m glad you asked about it because messages for key? predicate (the “is missing” one) are actually handled in a special way under the hood, and it’s something I do not like. I just haven’t come up with any idea how to represent them in a different way, which unfortunately complicates internals (a little bit, but still).
So I realize the below is very verbose compared to the current results output, but it gives I believe all the information necessary for the user to do whatever they want with it. A method could easily be implemented in dry-validation to reduce this structure to just messages for user convenience if desire. By having the whole structure though, it gives the caller the ability to take the information and do whatever it is they want with it, such as return it directly from an API, or even use the individual pieces and programatically do whatever the heck they want.
I also just saw issue #225 regarding hints. Those could of course easily be included in here as well for each field as either an array value, or taking a similar structure to the errors where the tokens are included.
{
quantity: {
errors: {
required: {message: 'is missing'},
size: {message: 'size must be within 1 - 5', tokens: {size_left: 1, size_right: 5}}
type: {message: 'must be an integer', tokens: {type: 'integer'}}
}
},
items: {
errors: {
max_size: {message: "cannot have more than 5 items", tokens: {num: 5}}
},
hints: {
max_size: {message: "choose up to 5 items", tokens: {num: 5}}
},
elements: [{0 =>
{
amount: {
errors: {
required: {message: 'is missing'},
min_size: {message: "must be greater than 0", tokens: {num: 0}}
}
}
}
}]
}
}
Please correct me if I’m wrong, but I think the items property having its own errors, as well as errors for it entities is fundamentally impossible at present. If the items property itself has errors, the errors from its individual items either aren’t validated, or they aren’t included in the result set.
So my next question is…does it have to be impossible? Like is there some fundamental reason it couldn’t be implemented? For the validations I want to do at times it would be helpful on the user’s end to receive information on both at the same time.
No it is technically possible, but it will require changes in how DSL works and how error hash structure is generated. When you use each in the DSL we create a conjunction rule saying “valid array && valid items”. With what you want to achieve is checking items unconditionally, which may introduce various caveats, like ie what if it’s not an array? How do we know when it’s safe to check the elements?