Required fields based on other fields value - error message


#1

I want to include, exclude fields based on the value of the method field.

Here is some pseudocode:

  required(:method).value(included_in?: ["a", "b"])

  if value(:method) == "a"
     required(:a).filled(:str?)
     optional(:b_1).filled(:none?)
     optional(:b_2).filled(:none?)
  else
     optional(:a).filled(:none?)
     required(:b_1).filled(:str?)
     required(:b_2).filled(:str?)
  end

I tired the following:

it {
  schema = Dry::Validation.Schema do
    required(:method).value(included_in?: ["a", "b"])
    optional(:a).filled(:str?)
    optional(:b_1).filled(:str?)
    optional(:b_2).filled(:str?)

    rule(a_rule: [:method, :a, :b_1, :b_2]) do |method, a, b_1, b_2|
      value(:method).format?(/^a$/).then(a.filled? & b_1.none? & b_2.none?)
    end

    # The same but different syntax
    rule(b_rule: [:method, :a, :b_1, :b_2]) do |method, a, b_1, b_2|
      method.format?(/^b$/) > (
        a.none? & b_1.filled? & b_2.filled?
      )
    end
  end

  errors = schema.call({
    method: "a",
  }).errors
  expect(errors).to eq({"a" => ["must be filled"]})
}

But I get the following error:

Failures:

  1) Validation invalid parameters custom should eq {"a"=>["must be filled"]}
     Failure/Error: expect(errors).to eq({"a" => ["must be filled"]})
     
       expected: {"a"=>["must be filled"]}
            got: {:a_rule=>["must be filled"]}
     
       (compared using ==)
     
       Diff:
       @@ -1,2 +1,2 @@
       -"a" => ["must be filled"],
       +:a_rule => ["must be filled"],

The error message is applied to the a_rule rule and not to the specific field.

Is there an option to achieve this differently?


#2

You could make them all optional and check their values based on the value of method.


#3

@solnic could you give me a code example?