# Reusable Validators/Contracts

**URL:** <https://discourse.dry-rb.org/t/reusable-validators-contracts/1485>\
**Category:** dry-validation\
**Created:** [June 21, 2022, 11:04pm UTC](https://discourse.dry-rb.org/t/reusable-validators-contracts/1485 "2022-06-21T23:04:48Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![bkuhlmann](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/bkuhlmann/32/557_2.png) [@bkuhlmann](https://discourse.dry-rb.org/u/bkuhlmann)\
**Post date:** [June 21, 2022, 11:04pm UTC](https://discourse.dry-rb.org/t/reusable-validators-contracts/1485/1 "2022-06-21T23:04:48Z")

</div>

Is it possible to reuse a validator which includes it’s schema _and rules_? Take the following, for example:

```ruby
#! /usr/bin/env ruby
# frozen_string_literal: true

# Save as `snippet`, then `chmod 755 snippet`, and run as `./snippet`.

require "bundler/inline"

gemfile true do
  source "https://rubygems.org"

  gem "amazing_print"
  gem "debug"
  gem "dry-validation"
end

class Inner < Dry::Validation::Contract
  json do
    required(:label).filled(:string)
  end

  rule :label do
    key.failure("value can only be: Prometheus") unless value == "Prometheus"
  end
end

class Outer < Dry::Validation::Contract
  json do
    required(:context).schema(Inner.schema)
  end
end

result = Outer.new.call context: {label: "Hades"}
ap result.errors.to_h # {}

```

Notice that I include `Inner` as a required schema within `Outer` but I don’t see an error for `:label` since only the schema is include _but not the rules_. Is there a way to fold in both the schema and the rules from another validator?

I was searching around and I see a lot of schema inclusion discussion but nothing with rules. I can’t see any support for this in the source code but wanted to ask anyway.

---

<div class="post-metadata">

**Author:** ![alassek](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/alassek/32/314_2.png) [@alassek](https://discourse.dry-rb.org/u/alassek)\
**Post date:** [June 22, 2022, 3:26am UTC](https://discourse.dry-rb.org/t/reusable-validators-contracts/1485/2 "2022-06-22T03:26:03Z")

</div>

@i2w was [doing some work](https://discourse.dry-rb.org/t/thoughts-on-dry-validation-wrt-composing-validations/904) on contract composition, but I don’t believe that has been completed.

---

<div class="post-metadata">

**Author:** ![solnic](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/solnic/32/779_2.png) [@solnic](https://discourse.dry-rb.org/u/solnic)\
**Post date:** [June 22, 2022, 7:40am UTC](https://discourse.dry-rb.org/t/reusable-validators-contracts/1485/3 "2022-06-22T07:40:18Z")

</div>

This is still scheduled as a new feature but it’s hard to tell when somebody will have time to actually implement it.

---

<div class="post-metadata">

**Author:** ![bkuhlmann](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/bkuhlmann/32/557_2.png) [@bkuhlmann](https://discourse.dry-rb.org/u/bkuhlmann)\
**Post date:** [June 22, 2022, 12:58pm UTC](https://discourse.dry-rb.org/t/reusable-validators-contracts/1485/4 "2022-06-22T12:58:20Z")

</div>

**Adam** : Thanks. Actually, I was spending time reading that thread yesterday but noticed the discussion was six years ago. 😅 I’m going to take a deeper look at that discussion today.

**Peter** : Hmm, yeah, maybe I can figure out some way to contribute back myself. Maybe. 🤞

---

<div class="post-metadata">

**Author:** ![bautrey37](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/bautrey37/32/762_2.png) [@bautrey37](https://discourse.dry-rb.org/u/bautrey37)\
**Post date:** [June 23, 2022, 9:38am UTC](https://discourse.dry-rb.org/t/reusable-validators-contracts/1485/5 "2022-06-23T09:38:15Z")

</div>

I’m using this workaround and it works great for me. [Composable contracts · Issue #593 · dry-rb/dry-validation · GitHub](https://github.com/dry-rb/dry-validation/issues/593#issuecomment-951395204)

---

<div class="post-metadata">

**Author:** ![bkuhlmann](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/bkuhlmann/32/557_2.png) [@bkuhlmann](https://discourse.dry-rb.org/u/bkuhlmann)\
**Post date:** [June 23, 2022, 9:40pm UTC](https://discourse.dry-rb.org/t/reusable-validators-contracts/1485/6 "2022-06-23T21:40:38Z")

</div>

**Brandon** : Thanks that was a good tip and callout. I ended up modifying the solution a bit further to great effect. I need to spend more time within this space but the following is working as a temporary solution:

```ruby
Dry::Validation.register_macro :contract do |macro:|
  result = macro.args.first.new.call value

  next if result.success?

  result.errors.each { |error| key(key.path.to_a + error.path).failure error.text }
end

```

Example:

```ruby
class Outer < Dry::Validation::Contract
  json { required(:inner).schema Inner.schema }

  rule(:inner).validate(contract: Inner)
end

result = Outer.new.call context: {label: "Hades"}
ap result.errors.to_h # {context: {label: ["value can only be: Prometheus"]}}

```
