# Need to understand Dry::Validation

**URL:** https://discourse.dry-rb.org/t/need-to-understand-dry-validation/1539
**Category:** dry-validation
**Created:** [October 21, 2022, 11:38am UTC](https://discourse.dry-rb.org/t/need-to-understand-dry-validation/1539 "2022-10-21T11:38:15Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![abc](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/abc/32/802_2.png) [@abc](https://discourse.dry-rb.org/u/abc)
#### Post date: [October 21, 2022, 11:38am UTC](https://discourse.dry-rb.org/t/need-to-understand-dry-validation/1539/1 "2022-10-21T11:38:15Z")

</div>

Hi everyone

I am learning `dry-rb` , specially Dry::Validations. There are no too many articles showing how to use it with Rails, for example. But for what I can find, including the dry-validation documentation, I see different ways to do what seems to be the same thing. But it’s not clear the real difference in practice.

First thing I would like to understand:

What is the difference between:

```auto
class NewUserContract < Dry::Validation::Contract
  params do
    required(:email).filled(:string)
    required(:age).value(:integer)
  end
end

```

and

```auto
class NewUserContract < Dry::Validation::Contract
  json do
    required(:email).filled(:string)
    required(:age).value(:integer)
  end
end

```

The second, difference I would like to understand is between: `filled`, `value` and `maybe`. Actually, I know that we use `maybe` when the value maybe `nil`. But, what about `filled` vs `value` ?

---

<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: [October 21, 2022, 8:52pm UTC](https://discourse.dry-rb.org/t/need-to-understand-dry-validation/1539/2 "2022-10-21T20:52:33Z")

</div>

Welcome! There isn’t a lot of documentation specific to Rails because Dry-rb is a toolkit intended for all Ruby code. There are a handful of specific Rails integrations provided by [dry-rails](https://dry-rb.org/gems/dry-rails/0.4/) but those are simply providing a convention for you to follow, it isn’t anything you couldn’t write yourself with only a little effort.

### Schema Processor Types

The difference between `params` and `json` in your example relates to the _schema processor_. Ultimately, this mostly just changes the default [dry-types](https://dry-rb.org/gems/dry-types/1.2/built-in-types/) that are used.

Schemas in dry-schema process keys in a series of steps:

1. Key Validation: is a required key missing
2. Key Coercion: transform a string key to symbol
3. Value Filter: screen out values before they are coerced
4. Value Coercion: apply any transformations defined in the type spec
5. Value Type: does the value pass the type spec
6. Value predicate: does the predicate (if defined) return true

Validation contracts tack on a final pass, applying rules to the entire schema that can encompass multiple keys.

The reason for `params` and `json` processor types comes from the different coercion rules you want to apply depending on whether you are dealing with HTTP params or JSON data.

For instance, it’s commonplace to see empty string returned in HTTP params that `params` automatically transforms to `nil`. That doesn’t happen with `json`. Likewise, JSON defines boolean types so those are not coerced, but HTTP params need to transform string values into booleans. Different rules for different use-cases.

### Macros

The distinction between `value`, `filled`, and `maybe` are different _macro types_.

`filled` is just a special-case macro for a very common thing you want to do: declare a type but ensure it’s non-empty. I believe I remember reading somewhere this is deprecated, so I would recommend using the predicate instead.

`value` is the primary macro for a value. It applies the type spec to the value to ensure its correctness, and coerce it if desired.

`value(:string)` is just a shorthand for `value(Dry::Types['strict.string'])`.

A macro can apply two rules to a value:

1. type spec
2. predicate

Predicates come from [dry-logic](https://dry-rb.org/gems/dry-logic/1.2/predicates/) and as you might suspect, they are just predicate methods that answer a question about an object.

So the `filled` macro is doing two things: a type spec, and a predicate.

```ruby
value(Dry::Types['strict.string'], :filled?)

```

So that will ensure that the value is a string, and it is non-empty.

The filled predicate may also be built into the type spec as a constraint using the same logic operation

```ruby
Types = Dry.Types(default: :strict)

module Types
  FilledString = String.constrained(filled: true)
end

class NewUserContract < Dry::Validation::Contract
  params do
    required(:email).value(Types::FilledString)
    required(:age).value(:integer)
  end
end

```

---

<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: [October 23, 2022, 4:44pm UTC](https://discourse.dry-rb.org/t/need-to-understand-dry-validation/1539/3 "2022-10-23T16:44:19Z")

</div>

> [@alassek](#):
>
> `filled` is just a special-case macro for a very common thing you want to do: declare a type but ensure it’s non-empty. I believe I remember reading somewhere this is deprecated, so I would recommend using the predicate instead

Just wanted to clarify that `filled` is not deprecated and it’s here to stay. This is a very common thing and it streamlines schema definitions pretty significantly. _Maybe_ we’ll move to type-based specs exclusively in a distant future once/if Ruby has a way to express rich types in its core lib.
