This topic is related to https://github.com/dry-rb/dry-validation/issues/179 on trying to get an error on unexpected Hash keys during validation with a dry-validation schema.
It would be nice if the expected keys are automatically derived from the required & optional keys mentioned in the schema. It would even be better if this would work on nested schemes as well.
The proposed ‘input’ predicate solution introduces a problem
- the unexpected hash keys are either already removed from the data param presented to the input predicate (weak/symbolized/… Dry::Type hash schema)
- or the raised Error is catched and ignored due to the ‘Safe’ class of dry-types ( form.hash/json.hash with strict Dry::Type hash schema --> the Safe class catches the error)
- or an error is raised and further error/hint processing is stopped (with strict Dry::Type hash schema)
If I understand it correctly :
- validation is handled using a pipeline starting with InputProcessing : https://github.com/dry-rb/dry-validation/blob/master/lib/dry/validation/schema.rb#L57
- input processor is selected based on Schema/Form/JSON schema selection or as an alternative the config.input_procesor param can be set
- the output of the ‘input processor’ pipeline step is used as input for the ‘input rule’ pipeline step
- json/form : here the ‘Safe’ Hash class is used which will catch any error thown for unexpected keys, so none of the Dry::types Hash schemes can be used to detect unexpected keys
- NOOP : just returns the input without any checks so cannot be used
- sanitizer : here the strict Dry::Types Hash scheme can be used which will raise an UnknownKeysError (https://github.com/dry-rb/dry-types/blob/master/lib/dry/types/hash/schema.rb#L140)
So only the last option could work, however:
- the UnknownKeysError is not catched so it will stop all further processing including any other errors/hints which could already be detected
- there is no way to combine for example symbolize keys with detection of unexpected keys, so additional combinations of Dry:Types Hash schemes should be added
Did I get this correctly?
If so, I tried an alternative approach in this POC commit https://github.com/pvmeerbe/dry-types/commit/e2ac4c07eec4eff692ee1b0eaf13566c80bf08c5
The idea is to always collect unexpected keys during parsing withDry:Types Hash schemes.
The current POC gathers all these keys (even from nested schemes) and returns it as a separate Hash structure
Some thoughts on this:
- The storage under the __ignored_data key feels clumsy, alternative could be to return an additional hash structure as second parameter with this info or even construct some kind of result object which contains the parsed data/unexpected keys/success-failure status ? However I’ve got no idea where this Schema#try method is used and whether changing this behavior would affect other code. for sure the dry-validation pipeline handling of Input processing should change
- I guess always collecting this data would have an impact on performance? I guess you don’t need this ignored_data info in many cases, so this seems overhead
Perhaps someone can give alternative approaches/improvements/comments on this topic?