Matching optional params schema against a nested schema

I just realized this works:

require "dry/schema"

inner_schema = Dry::Schema.Params do
  required(:path).filled(:string)
end

outer_schema = Dry::Schema.Params do
  required(:foo).maybe(:hash, inner_schema)
end

puts outer_schema.(foo: { path: "something" }).inspect
#<Dry::Schema::Result{:foo=>{:path=>"something"}} errors={}>

puts outer_schema.(foo: { path: "" }).inspect
#<Dry::Schema::Result{:foo=>{:path=>""}} errors={:foo=>{:path=>["must be filled"]}}>

puts outer_schema.(foo: "").inspect
#<Dry::Schema::Result{:foo=>nil} errors={}>

puts outer_schema.(foo: nil).inspect
#<Dry::Schema::Result{:foo=>nil} errors={}>

This is because a hash? check is applied separately from applying your schema. I can see how that’s confusing though - using an inner schema should probably imply a hash? check too :thinking: