dry-rb / dry-schema

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

Passing sum of Types as schema's value ignores defined schema on Hash Type #346

Open rindek opened 3 years ago

rindek commented 3 years ago

Working example:

schema = Dry::Schema.Params { required(:value).value(Types::Hash.schema(key: Types::Integer)) }
# output => #<Dry::Schema::Params keys=[{"value"=>["key"]}] rules={:value=>"key?(:value) AND key[value](hash? AND hash? AND set(key?(:key) AND key[key](int?)))"}>

schema.call(value: { key: 1 })
# output => #<Dry::Schema::Result{:value=>{:key=>1}} errors={}>

schema.call(value: { key: "a" })
# output => #<Dry::Schema::Result{:value=>{:key=>"a"}} errors={:value=>{:key=>["must be an integer"]}}>

When adding ex. Types::Integer as a Sum of Types, then it ignores the Schema of Hash and not allowing to pass the values at all, example:

schema = Dry::Schema.Params { required(:value).value(Types::Integer | Types::Hash.schema(key: Types::Integer)) }
# output => #<Dry::Schema::Params keys=["value"] rules={:value=>"key?(:value) AND key[value](int? OR hash?)"}>
# rules here does not show the Hash schemas rules, only check if it's a "hash?"

schema.call(value: { key: 1 })
# output => #<Dry::Schema::Result{:value=>{:key=>1}} errors={:value=>{:key=>["is not allowed"]}}>

schema.call(value: { key: "a" })
# output => #<Dry::Schema::Result{:value=>{:key=>"a"}} errors={:value=>{:key=>["is not allowed"]}}>

When adding config.validate_keys = false it works, but it skips validation of the Hash Schema, but it really does not make sense, since the schema is passed My expectation would be to allow both 1 and { key: 1 } as a value.

Gems versions: dry-schema (1.6.1) dry-types (1.5.1)