Comparing "values/params" (?) in Dry::Schema::Params

Hi,

I’m using Dry::Schema::Params and in my case it’d be great to compare “params”.

My example:

required(:from_after).filled(:date_time, gt?: DateTime.new(1970, 1, 1)) required(:from_before).filled(:date_time, gt?: DateTime.new(1970, 1, 1))

It is possible to compare :from_before with :from_after?
In example like this way:

required(:from_after).filled(:date_time, gt?: DateTime.new(1970, 1, 1), gteq: :from_before) ??

You want to use Dry::Validation and not Dry::Schema. That will give you access to rules, which can be applied to keys.

Untested

rule(:from_before, :from_after) do
  failure("after date must be earlier than before") if value[:from_before] < values[:from_after]
end

I know about this possibility, but I’d like to use it in Dry::Schema::Params.

It is possible?

It is not, it’s actually the reason why there’s dry-validation on top of dry-schema :sweat_smile:

1 Like

@flash-gordon @adam12 that makes sense to not mix schema with validations. How would you solve reusing validation rules across different contracts?

Let’s say we have:

Delivery = Dry::Schema.Params do
  required(:id).filled(:integer)
  # more schema restrictions
end

class DeliveriesAddition < Dry::Validation::Contract
  params do
    required(:deliveries).value(:array, min_size?: 1).each(Delivery)
  end

  rule(:deliveries).each do
    key.failure("from_after must be before from_before") if value[:from_after] >= value[:from_before]
    # some more rules
  end
end

class DeliveriesUpdate < Dry::Validation::Contract
  params do
    required(:deliveries).value(:array, min_size?: 1).each(Delivery)
  end

  rule(:deliveries).each do
    key.failure("from_after must be before from_before") if value[:from_after] >= value[:from_before]
    # some more rules that are the same as in DeliveriesAddition
  end
end

The goal here would be to not repeat the custom rules in every contract file but just use some common “mixin”.
I can see macros dry-rb - dry-validation v1.6 - Macros but looks like it would require defining every single rule by some custom name. Is it a way to go or is there a better way?