# Using contracts with schemas

**URL:** <https://discourse.dry-rb.org/t/using-contracts-with-schemas/844>\
**Category:** dry-validation\
**Created:** [July 20, 2019, 5:58am UTC](https://discourse.dry-rb.org/t/using-contracts-with-schemas/844 "2019-07-20T05:58:09Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![kminevskiy](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/kminevskiy/32/410_2.png) [@kminevskiy](https://discourse.dry-rb.org/u/kminevskiy)\
**Post date:** [July 20, 2019, 5:58am UTC](https://discourse.dry-rb.org/t/using-contracts-with-schemas/844/1 "2019-07-20T05:58:09Z")

</div>

Hi,

I was wondering how would I implement a contract that validates HTTP params using other contracts as “schemas” for its params argument.

For example, if I have this contract:

```
class UserSchema < Dry::Validation::Contract
  params do
    required(:first_name).value(:string, min_size?: 2)
    required(:last_name).value(:string, min_size?: 2)
    optional(:password).filled(:string)
    optional(:confirm_password).filled(:string)
  end

  rule(:password, :confirm_password) do
    if values[:password] == values[:confirm_password]
      key.failure('password does not match password confirmation.')
    end
  end
end

```

And then I have another contract:

```
class AccountSchema < Dry::Validation::Contract
  optional(:user1).hash(UserSchema)
  required(:user2).hash(UserSchema)
end

```

I’m not sure how to “express” the logic of the second contract - an argument to hash can be a dry validation schema params, but not a contract (and I need rules on the child contract to validate input).

Can something like this be implemented in the current version of dry-validation?  
Thanks!

---

<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:** [July 20, 2019, 9:15am UTC](https://discourse.dry-rb.org/t/using-contracts-with-schemas/844/2 "2019-07-20T09:15:25Z")

</div>

> Can something like this be implemented in the current version of dry-validation?

No, it’s not possible to mix schemas and contracts. I would just define a macro and reuse it:

```ruby
class AppContract < Dry::Validation::Contract
  register_macro(:password_confirmation) do
    unless values[:password].eql?(values[:confirm_password])
      key.failure('password does not match password confirmation.')
    end
  end
end

UserSchema = Dry::Schema.Params do
  required(:first_name).value(:string, min_size?: 2)
  required(:last_name).value(:string, min_size?: 2)
  optional(:password).filled(:string)
  optional(:confirm_password).filled(:string)
end

class AccountContract < AppContract
  optional(:user1).hash(UserSchema)
  required(:user2).hash(UserSchema)

  rule(:user1).validate(:password_confirmation)
  rule(:user2).validate(:password_confirmation)
end

```

This could be automated, so we may consider adding some features to make it nicer in the future.

---

<div class="post-metadata">

**Author:** ![kminevskiy](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/kminevskiy/32/410_2.png) [@kminevskiy](https://discourse.dry-rb.org/u/kminevskiy)\
**Post date:** [July 22, 2019, 8:15am UTC](https://discourse.dry-rb.org/t/using-contracts-with-schemas/844/3 "2019-07-22T08:15:09Z")

</div>

Thanks, @solnic!
