# How to perform checks based on the result of the previous check

**URL:** https://discourse.dry-rb.org/t/how-to-perform-checks-based-on-the-result-of-the-previous-check/340
**Category:** dry-validation
**Created:** [September 13, 2017, 1:19am UTC](https://discourse.dry-rb.org/t/how-to-perform-checks-based-on-the-result-of-the-previous-check/340 "2017-09-13T01:19:04Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![bethesque](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/bethesque/32/129_2.png) [@bethesque](https://discourse.dry-rb.org/u/bethesque)
#### Post date: [September 13, 2017, 1:19am UTC](https://discourse.dry-rb.org/t/how-to-perform-checks-based-on-the-result-of-the-previous-check/340/1 "2017-09-13T01:19:04Z")

</div>

I would like to assert that a value is a string is not blank (eg. " "). If I submit a number, I want only the message “must be a string” to appear, however, the “cannot be blank” message also appears. I have tried to debug this, and it seem that the `not_blank?` rule is failed automatically if the `str?` rule fails, as my debugger did not break when put in the `not_blank?` method. Is there a way to short circuit the checking, so that `not_blank?` is only checked if `str?` is true? I’m sure this has been answered before, however, I’ve had a bit of a search and cannot find an answer, and I’m not sure of the terms to search on. Thanks in advance.

```auto
require 'dry-validation' #v0.11.0

form = Dry::Validation.Form do
  configure do
    def not_blank?(value)
      !blank?(value)
    end

    def blank?(value)
      value.is_a?(String) && value.strip.empty?
    end

    def self.messages
      super.merge(
        en: { errors: { not_blank?: 'cannot be blank' } }
      )
    end
  end

  required(:name_one) { str? & not_blank? }
  required(:name_two).filled(:str?, :not_blank?)
  required(:name_three) { str? & (str? > not_blank?) }
end

puts form.call(name_one: 1, name_two: 2, name_three: 3).messages
# => {:name_one=>["must be a string", "cannot be blank"], :name_two=>["must be a string", "cannot be blank"], :name_three=>["must be a string", "cannot be blank"]}

```

---

<div class="post-metadata">

### Author: ![smaximov](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/smaximov/32/165_2.png) [@smaximov](https://discourse.dry-rb.org/u/smaximov)
#### Post date: [October 12, 2017, 10:38am UTC](https://discourse.dry-rb.org/t/how-to-perform-checks-based-on-the-result-of-the-previous-check/340/2 "2017-10-12T10:38:35Z")

</div>

> [@bethesque](#):
>
> Is there a way to short circuit the checking, so that not\_blank? is only checked if str?

In fact, the checks _are_ short-circuit, and if one check fails the rest are skipped. To understand why you are getting extra messages you need to understand what kinds of error messages `dry-validation` has. It is described [here](http://dry-rb.org/gems/dry-validation/basics/working-with-schemas/), but I will give you a summary:

- `errors`: messages which are the result of failing predicates;
- `hints`: messages for predicates which _weren’t evaluated_ because an earlier predicate had failed;
- `messages`: `errors` and `hints` combined.

So what you need is to use `Dry::Validation::Result#errors` instead of `Dry::Validation::Result#messages` as you don’t need hints.

Here’s an example:

```ruby
require 'bundler/inline'

gemfile(true) do
  source 'https://rubygems.org'

  gem 'dry-validation', '~> 0.11.1'
  gem 'rspec', require: 'rspec/autorun'
end

module BlankChecker
  def self.call(value)
    !value.to_s.strip.empty?
  end
end

Form = Dry::Validation.Form do
  configure do
    def not_blank?(value)
      # Delegate the check to a helper object because
      # frozen form instances cannot be mocked.
      BlankChecker.call(value)
    end

    def self.messages
      super.merge(
        en: { errors: { not_blank?: 'cannot be blank' } }
      )
    end
  end

  required(:name).filled(:str?, :not_blank?)
end

RSpec.describe 'Dry::Validation error messages' do
  subject(:result) { Form.(name: name) }

  context 'when input is a valid string' do
    let(:name) { 'George' }

    it "don't have error messages" do
      # Blank check is performed:
      expect(BlankChecker).to receive(:call).and_return(true)

      expect(result.messages).to be_empty
      expect(result.errors).to be_empty
      expect(result.hints).to be_empty
    end
  end

  context 'when input is a blank string' do
    let(:name) { ' ' }

    it 'have an error and no hints' do
      # Blank check is performed:
      expect(BlankChecker).to receive(:call).and_return(false)

      expect(result.messages).to eq(name: ['cannot be blank'])
      expect(result.errors).to eq(result.messages)
      expect(result.hints[:name]).to be_empty
    end
  end

  context 'when input is not a string' do
    let(:name) { 0xDEADBABE }

    it 'have an error and a hint' do
      # Blank check is NOT performed!
      expect(BlankChecker).not_to receive(:call)

      expect(result.messages[:name]).to eq(result.errors[:name] + result.hints[:name])
      expect(result.errors[:name]).to eq(['must be a string'])
      expect(result.hints[:name]).to eq(['cannot be blank'])
    end
  end
end

```

---

<div class="post-metadata">

### Author: ![bethesque](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/bethesque/32/129_2.png) [@bethesque](https://discourse.dry-rb.org/u/bethesque)
#### Post date: [October 12, 2017, 10:36pm UTC](https://discourse.dry-rb.org/t/how-to-perform-checks-based-on-the-result-of-the-previous-check/340/3 "2017-10-12T22:36:31Z")

</div>

That’s awesome, thank you. I had not seen the documentation for that feature.
