# How to validate interdependent arguments?

**URL:** <https://discourse.dry-rb.org/t/how-to-validate-interdependent-arguments/662>\
**Category:** dry-validation\
**Created:** [December 4, 2018, 5:55pm UTC](https://discourse.dry-rb.org/t/how-to-validate-interdependent-arguments/662 "2018-12-04T17:55:44Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![harpocrates12](https://avatars.discourse-cdn.com/v4/letter/h/59ef9b/32.png) [@harpocrates12](https://discourse.dry-rb.org/u/harpocrates12)\
**Post date:** [December 4, 2018, 5:55pm UTC](https://discourse.dry-rb.org/t/how-to-validate-interdependent-arguments/662/1 "2018-12-04T17:55:44Z")

</div>

Hi,

I want to validate this:

params: start\_date, end\_date, expiry\_date

1. a start\_date must either be before or on the same day as the end\_date

2. an end\_date must either be after or on the same day as the start\_date

3. the expiry\_date must be before the start\_date

4. all dates must be in the future

5. if one date is present then all dates must be present:

```
valid:
  start is present
  end is present
  expiry is present
    
valid:
  start is not present
  end is not present
  expiry is not present
    
    
invalid:
  start is not present
  end is present
  expiry is present

```

Otherwise dates do not need to be present.

I came up with the following:

```auto
schema = Dry::Validation.Schema do
  configure do
    def self.messages
      super.merge(
        errors: {
          dates: 'must be in the future!',
          _dates: 'must comply with (expiry < start <= end) !',
        }
      )
    end
  end

  required(:start_date) { filled? }
  required(:end_date) { filled? }
  required(:expiry_date) { filled? }

  validate(
    dates: %i[start_date end_date expiry_date]
  ) do |start_date, end_date, expiry_date|
    today = Date.today

    (start_date > today) & (end_date > today) & (expiry_date > today)
  end

  validate(
    _dates: %i[start_date end_date expiry_date]
  ) do |start, end_date, expiry_date|
      (start <= end_date) && (start > expiry_date)
  end
end

schema.call(date_params) if date_params.any?

```

What I am missing now is a way to provide error messages for each individual intrusion  
e.g.  
dates must not be in the past!  
expiry\_date should be before start\_date!  
start\_date must not be after end\_date!  
end\_date must not be before start\_date!

I tried it with custom predicates, the only problem being that I want the predicates  
only to be evaluated if the dates are filled otherwise not.

Any suggestions? Not sure if dry validation blocks are the best match for this 🙂
