Hi,
My use case is that I want to validate an input that requires different validations based on one key of that input.
Example: I accept a URL object as input and I want to perform different validations for HTTP and FTP schemes.
I thought about branching before running the schema validations, but that disallows using each
to validate arrays in one go. I tried using custom validation blocks (when
combined with and
) but then I lost built-in error messages and hints. Can I achieve such branching in any way?
HttpSchema = Dry::Validation.Schema do
required(:method).filled?(:str?)
end
FtpSchema = Dry::Validation.Schema do
required(:user).filled?(:str?)
end
UrlSchema = Dry::Validation.Schema do
required(:scheme).filled(:str?).when(format?(/^http/)) do
schema(HttpSchema) # pseudo-code
end
required(:scheme).filled(:str?).when(format?(/^ftp/)) do
schema(FtpSchema) # pseudo-code
end
end
UrlsSchema = Dry::Validation.Schema do
required(:urls).filled { each { schema(UrlSchema) } }
end
it 'is valid when method provided with http scheme' do
expect(UrlsSchema.call(urls: [{scheme: 'http', method: 'foo'}]).success?).to eq(true)
end
it 'is valid when user provided with ftp scheme' do
expect(UrlsSchema.call(urls: [{scheme: 'ftp', user: 'bar'}]).success?).to eq(true)
end
Edit:
Note that in reality HttpSchema
and FtpSchema
equivalents are much more complex so using custom validation blocks is a problem.