dry-rb / dry-schema

Coercion and validation for data structures
https://dry-rb.org/gems/dry-schema
MIT License
415 stars 108 forks source link

Key validation shouldn't happen when no schema for a hash is set #452

Open flash-gordon opened 1 year ago

flash-gordon commented 1 year ago

Describe the bug

There can be a case when no schema for a hash is set. In such a case, there's not need to validate keys. I might be wrong but it's just logical to me.

To Reproduce

DemoSchema = Dry::Schema.define do
  config.validate_keys = true

  required(:addresses).array(:hash)
end

DemoSchema.call({addresses: [{number: "oo"}]}) 
=> #<Dry::Schema::Result{:addresses=>[{:number=>"oo"}]} errors={:addresses=>{0=>{:number=>["is not allowed"]}}} path=[]>

Expected behavior

The validation passes. We didn't specify any key for nested hashes, key validation shouldn't be applied in such cases. I would expect such values to be validated at later stages with rules or custom code.

My environment

flash-gordon commented 1 year ago

Discovered in #450

jmtame commented 1 year ago

Bumping this

JanecekJ commented 1 year ago

This would be really helpful.

JanecekJ commented 11 months ago

Is there any way how to bump this up more than giving the like?

Or is there any way how to achieve similar behaviour?

What I would need is for validation to throw error, if the input hash has a key (attribute) I am not expecting, but also allow one of the defined keys which value is hash with undefined keys/structure.

Example to allow ({*} is hash with undefined keys/structure)

{
  'foo' => 'abc',
  'bar' => {*}
}

Example to disallow (because baz is not specified/allowed)

{
  'foo' => 'abc',
  'bar' => {*},
  'baz' =>'def'
}
JanecekJ commented 11 months ago

@flash-gordon Hello, I managed to put together some code, that is trying to tackle this issue. I am not really sure if it is the right approach. Also not really sure if it is already in a state for PR.

https://github.com/JanecekJ/dry-schema/tree/fix-hash-without-schema-validation

Can you maybe give me a pointer if this could work or it is not a way to go?