dry-schema
dry-schema copied to clipboard
Unexpected keys present in the result when attribute is defined to be hash or array of hashes
Describe the bug
I need a Contract that is valid for hashes where the :data
key is either a Hash
with defined structure or an Array
of such Hash
es:
{ data: { type: 'records' } }
OR
{ data: [{ type: 'records' }] }
Following contracts work as expected:
class Contract1 < Dry::Validation::Contract
params do
required(:data) do
hash { required(:type).filled(:string) }
end
end
end
Contract1.new.call({ data: { type: 'records', unexpected: 1 } })
# <Dry::Validation::Result{:data=>{:type=>"records"}} errors={}>
class Contract2 < Dry::Validation::Contract
params do
required(:data) do
array(:hash) { required(:type).filled(:string) }
end
end
end
Contract2.new.call({ data: [{ type: 'records', unexpected: 1 }] })
# <Dry::Validation::Result{:data=>[{:type=>"records"}]} errors={}>
To Reproduce
Unfortunately a Contract that combines those two rules leaks unexpected properties when :data
contains a Hash
:
class Contract1or2 < Dry::Validation::Contract
params do
required(:data) do
hash { required(:type).filled(:string) } |
array(:hash) { required(:type).filled(:string) }
end
end
end
Contract1or2.new.call({ data: { type: 'records', unexpected: 1 } })
# <Dry::Validation::Result{:data=>{:type=>"records", :unexpected=>1}} errors={}>
It works in the second scenario:
Contract1or2.new.call({ data: [{ type: 'records', unexpected: 1 }] })
# <Dry::Validation::Result{:data=>[{:type=>"records"}]} errors={}>
Validation also seems to work:
Contract1or2.new.call({ data: { unexpected: 1 } })
# <Dry::Validation::Result{:data=>{:unexpected=>1}} errors={:data=>{:type=>["is missing"]}}>
Expected behavior Result does not include unexpected keys:
Contract1or2.new.call({ data: { type: 'records', unexpected: 1 } })
# <Dry::Validation::Result{:data=>{:type=>"records"}} errors={}>
Your environment
- Affects my production application: NO
- Ruby version: 2.6.3
- OS: linux
Closed because it's related to dry-validation
- https://github.com/dry-rb/dry-validation/issues/643
Reopening, because it can be reproduced with Dry::Schema
schema = Dry::Schema.Params do
required(:data) do
hash { required(:type).filled(:string) } |
array(:hash) { required(:type).filled(:string) }
end
end
actual:
schema.call(data: { type: 'tests', undefined: 1 })
# <Dry::Schema::Result{:data=>{:type=>"tests", :undefined=>1}} errors={}>
expected:
schema.call(data: { type: 'tests', undefined: 1 })
# <Dry::Schema::Result{:data=>{:type=>"tests"}} errors={}>
Thanks for reporting this. I'm scheduling the fix for 2.0.0 because it's going to be simpler to do once a couple other improvements are done.