How to validate with schema block after maybe

I have a case where I need to validate a structure which is allowed to be nil… sounds odd but bear with me. It doesn’t look like nested validations are respected when the parent is allowed to be nil.

require "dry-validation"

SomeSchema = Dry::Validation.Schema do
  optional(:parent_hash).maybe.schema do
    required(:child_hash).schema do
      required(:attribute).filled(:str?)
    end
  end
end

puts SomeSchema.(
  parent_hash: {
    child_hash: { attribute: "Foobar" }
  },
).inspect

puts SomeSchema.(
  parent_hash: {
    child_hash: { attribute: nil }
  },
).inspect

puts SomeSchema.(
  parent_hash: {
    child_hash: nil
  },
).inspect
#<Dry::Validation::Result output={:parent_hash=>{:child_hash=>{:attribute=>"Foobar"}}} errors={}>
#<Dry::Validation::Result output={:parent_hash=>{:child_hash=>{:attribute=>nil}}} errors={}>
#<Dry::Validation::Result output={:parent_hash=>{:child_hash=>nil}} errors={}>

Removing the maybe I get this:

#<Dry::Validation::Result output={:parent_hash=>{:child_hash=>{:attribute=>"Foobar"}}} errors={}>
#<Dry::Validation::Result output={:parent_hash=>{:child_hash=>{:attribute=>nil}}} errors={}>
#<Dry::Validation::Result output={:parent_hash=>{:child_hash=>nil}} errors={:parent_hash=>{:child_hash=>["must be filled"]}}>

Even with the maybe removed the validation is only so deep.

Any help is appreciated.

THE SECRET SAUCE IS PASSING A BLOCK TO maybe

optional(:parent_hash).maybe.schema do

Does not work, whereas:

optional(:parent_hash).maybe do
  schema do

Does.

Glad you figured it out. In 1.0.0 we’ll either add support for chaining, or at least raise an error when somebody is trying to chain.