# Build dry-validations dynamically

**URL:** <https://discourse.dry-rb.org/t/build-dry-validations-dynamically/164>\
**Category:** dry-validation\
**Created:** [November 23, 2016, 7:27pm UTC](https://discourse.dry-rb.org/t/build-dry-validations-dynamically/164 "2016-11-23T19:27:46Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![jagse](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/jagse/32/67_2.png) [@jagse](https://discourse.dry-rb.org/u/jagse)\
**Post date:** [November 23, 2016, 7:27pm UTC](https://discourse.dry-rb.org/t/build-dry-validations-dynamically/164/1 "2016-11-23T19:27:47Z")

</div>

Hey guys,

I’ve discovered dry-validation a few days ago and I’m currently trying it out on a project. Now I’ve come to the point where I was thinking about creating schemas dynamically. If I understand correct I can simply create my own schema class with something like:

```auto
class Schema < Dry::Validation::Schema::Form
  define! do
    required(:whatever).value(:str?)
  end
end

```

Let’s say I would like to pass in which fields of my schema are optional since this differs from case to case. Is there any non hacky way to achieve this?

---

<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:** [December 2, 2016, 10:34am UTC](https://discourse.dry-rb.org/t/build-dry-validations-dynamically/164/2 "2016-12-02T10:34:34Z")

</div>

We have a rather sophisticated mechanism for building schemas dynamically by using a formalized rule AST (provided by dry-logic). The DSL is a front-end for building that AST, but if somebody wants to define a schema dynamically I would recommend building an AST and then it’s a matter of passing it to schema builder. Please let me know if this is something you’d like to do, I can provide some examples.

---

<div class="post-metadata">

**Author:** ![jagse](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/jagse/32/67_2.png) [@jagse](https://discourse.dry-rb.org/u/jagse)\
**Post date:** [January 31, 2017, 8:56pm UTC](https://discourse.dry-rb.org/t/build-dry-validations-dynamically/164/3 "2017-01-31T20:56:31Z")

</div>

Thanks for you reply. It’s been a while. But yeah if you would have some examples on how to build an AST, I would appreciate it! I love the idea of dry-validation. Thanks for your amazing work guys!

---

<div class="post-metadata">

**Author:** ![andreimoment](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/andreimoment/32/555_2.png) [@andreimoment](https://discourse.dry-rb.org/u/andreimoment)\
**Post date:** [August 22, 2020, 11:09pm UTC](https://discourse.dry-rb.org/t/build-dry-validations-dynamically/164/4 "2020-08-22T23:09:29Z")

</div>

I would love to see an example for this, too. Thank you.

---

<div class="post-metadata">

**Author:** ![andreimoment](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/andreimoment/32/555_2.png) [@andreimoment](https://discourse.dry-rb.org/u/andreimoment)\
**Post date:** [August 23, 2020, 5:34pm UTC](https://discourse.dry-rb.org/t/build-dry-validations-dynamically/164/5 "2020-08-23T17:34:55Z")

</div>

Wondering, were you able to build schemas dynamically? If yes, could you share an example? Thank you.

---

<div class="post-metadata">

**Author:** ![delonnewman](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/delonnewman/32/911_2.png) [@delonnewman](https://discourse.dry-rb.org/u/delonnewman)\
**Post date:** [August 25, 2020, 6:21pm UTC](https://discourse.dry-rb.org/t/build-dry-validations-dynamically/164/6 "2020-08-25T18:21:17Z")

</div>

I’d be interested some examples as well.

---

<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:** [August 27, 2020, 8:35am UTC](https://discourse.dry-rb.org/t/build-dry-validations-dynamically/164/7 "2020-08-27T08:35:38Z")

</div>

Things changed a lot since 2017 😅 The main idea of using an AST is still the same though but there are now various nitty-gritty details that make it a bit hard to instantiate a schema object manually.

In order to make this easy we’d have to add a public API that would take a list of rules and turn that into a schema object. Right now this is as far as you can go:

```ruby
dry-schema> s = schema { required(:name).value(:string) }
=> #<Dry::Schema::Processor keys=[:name] rules={:name=>"key?(:name) AND key[name](str?)"}>
dry-schema> ast = s.to_ast
=> [:set, [[:and, [[:predicate, [:key?, [[:name, :name], [:input, Undefined]]]], [:key, [:name, [:predicate, [:str?, [[:input, Undefined]]]]]]]]]]
dry-schema> c = Dry::Schema::Compiler.new
=> #<Dry::Schema::Compiler:0x00007fb6acad61b8 @predicates=#<Dry::Schema::PredicateRegistry:0x00007fb6acad6280 @has_predicate=#<Method: Kernel#respond_to?>, @predicates=Dry::Logic::Predicates>>
dry-schema> rules = c.([ast])
=> [#<Dry::Logic::Operations::Set rules=[#<Dry::Logic::Operations::And rules=[#<Dry::Logic::Rule::Predicate::Predicate2Arity1Curried predicate=#<Method: Dry::Logic::Predicates.key?> options={:args=>[:name], :arity=>2}>, #<Dry::Logic::Operations::Key rules=[#<Dry::Logic::Rule::Predicate::Predicate1Arity predicate=#<Method: Dry::Logic::Predicates.str?> options={:args=>[], :arity=>1}>] options={:name=>:name, :evaluator=>#<Dry::Logic::Evaluator::Key path=[:name]>, :path=>:name}>] options={:hints=>false}>] options={}>]

```

Now, having a list of rules is just not enough to instantiate a schema. A schema uses an internal “step processor” that supports before/after hooks and has three main steps that are applied when a schema validates data, one of those steps is “rule applier” and _that_ is what needs the rules produced by the compiler.

Please remember that I am not saying it’s not possible, I’m just saying it requires a bit of a ceremony 🙂 See what the DSL [is doing](https://github.com/dry-rb/dry-schema/blob/391544cdaf30e56a66faf89f0e520806609567c5/lib/dry/schema/dsl.rb#L198-L210) to get an idea of what I’m talking about.

I’m definitely interested in adding a first-class public API to make this very simple though - please feel free to report an issue and I’ll schedule it for 2.0.0 release.

---

<div class="post-metadata">

**Author:** ![andreimoment](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/andreimoment/32/555_2.png) [@andreimoment](https://discourse.dry-rb.org/u/andreimoment)\
**Post date:** [September 21, 2022, 4:57am UTC](https://discourse.dry-rb.org/t/build-dry-validations-dynamically/164/8 "2022-09-21T04:57:01Z")

</div>

I am wondering if anything has changed since 2020 on this?

Looking to build dry validations on the fly for user-defined form fields and validations - a scenario where the activerecord validations cannot be used.

What would be the best approach to building validation rules on the fly and running them?

---

<div class="post-metadata">

**Author:** ![postmodern](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/postmodern/32/696_2.png) [@postmodern](https://discourse.dry-rb.org/u/postmodern)\
**Post date:** [May 13, 2023, 9:09am UTC](https://discourse.dry-rb.org/t/build-dry-validations-dynamically/164/10 "2023-05-13T09:09:43Z")

</div>

For those wondering, I figured out how to dynamically build schemas using `dry-schemas` by calling `Dry::Schema::DSL` directly.

```ruby
dsl = Dry::Schema::DSL.new(processor_type: Dry::Schema::Params)
dsl.required(:foo).filled(:string)
dsl.optional(:bar).maybe(:integer)
# ...
params_schema = dsl.call
params_schema.call(params)
# => #<Dry::Schema::Result{...}

```

I assume you could do something similar with `dry-validation`?
