From 0df4e1c4f749c3f13e3f0269e02a554b90c1d475 Mon Sep 17 00:00:00 2001 From: Tadeusz Niemiec Date: Wed, 19 Aug 2020 14:41:00 +0200 Subject: [PATCH] Support per-key custom errors for array paths --- lib/dry/validation/messages/resolver.rb | 5 +++++ spec/fixtures/messages/errors.en.yml | 2 ++ .../contract/class_interface/rule/each_spec.rb | 13 +++++++++++++ 3 files changed, 20 insertions(+) diff --git a/lib/dry/validation/messages/resolver.rb b/lib/dry/validation/messages/resolver.rb index 03a0fcdf..56990418 100644 --- a/lib/dry/validation/messages/resolver.rb +++ b/lib/dry/validation/messages/resolver.rb @@ -69,6 +69,11 @@ def message(rule, tokens: EMPTY_HASH, locale: nil, full: false, path:) template, meta = messages[rule, msg_opts.merge(path: keys.last)] unless template end + if !template && keys.size > 1 + non_index_keys = keys.reject { |k| k.is_a?(Integer) } + template, meta = messages[rule, msg_opts.merge(path: non_index_keys.join(DOT))] + end + unless template raise MissingMessageError, <<~STR Message template for #{rule.inspect} under #{keys.join(DOT).inspect} was not found diff --git a/spec/fixtures/messages/errors.en.yml b/spec/fixtures/messages/errors.en.yml index 44388240..732e8dd0 100644 --- a/spec/fixtures/messages/errors.en.yml +++ b/spec/fixtures/messages/errors.en.yml @@ -17,3 +17,5 @@ en: wrong: "not right" age: toddler: "should be included in %{list}" + small_integers: + too_big: "is too big!" diff --git a/spec/integration/contract/class_interface/rule/each_spec.rb b/spec/integration/contract/class_interface/rule/each_spec.rb index 744098d4..218ae823 100644 --- a/spec/integration/contract/class_interface/rule/each_spec.rb +++ b/spec/integration/contract/class_interface/rule/each_spec.rb @@ -14,6 +14,7 @@ def self.name params do required(:nums).array(:integer) + optional(:small_integers).array(:integer) optional(:hash).hash do optional(:another_nums).array(:integer) end @@ -23,6 +24,10 @@ def self.name key.failure("invalid") if value < 3 end + rule(:small_integers).each do + key.failure(:too_big) if value > 9 + end + rule(hash: :another_nums).each do key.failure("invalid") if value < 3 end @@ -51,6 +56,14 @@ def self.name it "passes block options" do expect(contract.(nums: [10, 20]).context[:sum]).to eql(30) end + + it "returns error from the rule namespace without an index" do + contract_class.config.messages.load_paths << SPEC_ROOT.join("fixtures/messages/errors.en.yml").realpath + expect(contract.(small_integers: [11, 12], nums: [1]).errors.to_h) + .to eql(small_integers: { 0 => ["is too big!"], + 1 => ["is too big!"]}, + nums: { 0 => ["invalid"] }) + end end context "using a simple macro" do