# Choosing a schema based on the value of a property

**URL:** <https://discourse.dry-rb.org/t/choosing-a-schema-based-on-the-value-of-a-property/372>\
**Category:** dry-validation\
**Created:** [October 23, 2017, 2:06pm UTC](https://discourse.dry-rb.org/t/choosing-a-schema-based-on-the-value-of-a-property/372 "2017-10-23T14:06:33Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![urmastalimaa](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/urmastalimaa/32/148_2.png) [@urmastalimaa](https://discourse.dry-rb.org/u/urmastalimaa)\
**Post date:** [October 23, 2017, 2:06pm UTC](https://discourse.dry-rb.org/t/choosing-a-schema-based-on-the-value-of-a-property/372/1 "2017-10-23T14:06:34Z")

</div>

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?

```ruby
  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.
