[dry-validation] Improve base rules with names

Hey,
in my current project I have lots of use-cases, where I would need to name base rules. Here’s some pseudo code:

class BookingContract < Dry::Validation::Contract
  params do
    required(:reference_number).value(:string)
    required(:type).value(:string)
    ...
  end

  rule(name: :must_be_in_external_system, keys: [:reference_number, :type]) do |context:|
    payment = ext_payment_api.find(type: values[:type], reference_number: values[:reference_number])
    unless (payment.nil?)
      context[:payment] = payment
    else 
      base.failure("no payment available in external system!")
    end
  end

  rule(name: :payment_has_to_be_paid) do |context:|
    next if base_rule_error?(:must_be_in_external_system)
    base.failure("payment has not yet been paid") if context[:payment].paid?
  end

  rule(name: :correct_payment_type) do |context:|
    next if base_rule_error?(:must_be_in_external_system)
    base.failure("payment has to be of type TEST") if context[:payment].type != "TEST"
  end
end

What do you think about the idea? I think it would offer new options and make rules more readable.

Thanks
best regards

2 Likes

I agree here, this is the idea that I also had.

Right now the biggest disadvantage of dry-validation that I see is the fact that rules are anonymous. To understand what is validated in the rule, I need to read the code. The workaround for that are comment annotations, but that is not good enough, I’d rather have it as a code.

The internal rule name could be also useful in debugging and referencing. Eg. you could tell your colleague that :must_be_in_external_system rule is incorrect, it does not need to be in external system, instead of pointing the “rule on line 10” or “rule about [:reference_number, :type]”.

My heart falls seeing that this idea stays here without any answer from 2021. Please, maintainers, at least tell us what do you think :).