Conditional rules

I’m coming here after upgrading to 1.4 of dry-validation, but AFAIK this wasn’t available before, or I didn’t bother to ask back then. Basically, I’d like to apply a set of conditional rules based on the value (or any other condition) of another field. Like, let’s say, I have these two types of payment:

{"payment" => {"type": "card", "number": "1234123412341234"...}
{"payment" => "type": "transfer", "iban": "GB05 1234 1234 1234"...}

I’d like to apply a sub-schema dependent on the type field, in this example. Is there an easy to approach this? In my case, I’d have more than one conditional field to validate, so this is not as easy as “just create a rule and early-exit based on that initial condition”, as I end up with several rules with the same first condition in this case.

Could you provide a full example of what you would like to have?

I actually didn’t think of a proposal on how to make this possible (I’d first like to know whether it’s already supported), but from the top of my head, I can think of the following:

multiple params calls

One could allow params to be called multiple times, and allow options on it:

params(SchemaWithNumber, if: -> { values[:type] == "card" })
params(SchemaWithIban, if: -> { values[:type] == "transfer" })

optional block

One could extend a rule with an optional block, if the initial parameter could be validated with no errors:

required(:type).filled(:string, included_in?: %w[card transfer]) do |type|
  if type == "card"
    required(:number)....
  elsif type == "transfer"
    required(:iban)......
 ....

This is what I could come up with from the back of my head.

Is it currently supported?

Hi! In a very similar case I made 2 different contracts for each case (by reusing a common schema)

schema(BaseSchema) do
  required(:iban).value(:string)
end

...

schema(BaseSchema) do
  required(:number).value(:string)
end

Then I made a Validate operation (dry-transaction) which uses corresponding contract depending on the type. Well, first you have to also validate type attribute alone before this

Another alternative is to make those fields optional then use rule DSL to enforce their constraints based on the type.