These are chat archives for dry-rb/chat

2nd
Feb 2018
Joshua Hansen
@binarypaladin
Feb 02 2018 00:33

I've been messing with dry-validations for a while and in general, we have no issue getting the validation results that we want. The biggest challenge I keep running into is with error messages. Consider this example:

Dry::Validation.Schema do
  optional(:att1).filled(:str?)
  optional(:att2).filled(:str?)

  rule(only_one: [:att1, :att2]) do |att1, att2|
    att2.filled? ^ att1.filled?
  end
end

The rule does what I want. It ensures that only one or the other can be filled and that they can't both be nil. However, the error message is the issue. The current behavior is going to return :only_one=>["must be filled"] which is not what I want.

The keys on errors are problematic. The key only_one doesn't relate to anything the client is sending us. In Rails I used to use base by convention for complex rules that covered multiple fields and the error message was a full sentence.

With dry-validations I could cheat and do something like this:

Dry::Validation.Schema do
  optional(:att1).filled(:str?)
  optional(:att2).filled(:str?)

  rule(base: [:att1, :att2]) do |att1, att2|
    att2.filled? ^ att1.filled?
  end
end

With an errors file like this:

en:
  errors:
    rules:
      base:
        filled?: 'You must provide either att1 or att2.'

However, if there is any other rule for base that uses filled? it's going to show the same error. I can namespace, but that wouldn't help if I had two rules in the same namespace that used filled? for resolution. So, my questions are:

  1. Is there a way to give a uniquely named rule a different key for its message? (e.g. call the rule only_one but have the error hash return :base=>["You must provide either att1 or att2."])
  2. Is there some kind of general convention for errors that don't line up with any particular attribute name? (e.g. base from ActiveModel land)
  3. Am I just flat out thinking about all of this the wrong way and there's a better way to accomplish what I want?