From 1bf0e0c3ff31bd4c74fc57dda0ef01b9ca89041b Mon Sep 17 00:00:00 2001 From: Brandon Autrey Date: Tue, 10 May 2022 11:03:58 +0300 Subject: [PATCH 1/2] rubocop -a --- lib/dry/validation/values.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/dry/validation/values.rb b/lib/dry/validation/values.rb index 272745f4..588f6db4 100644 --- a/lib/dry/validation/values.rb +++ b/lib/dry/validation/values.rb @@ -65,7 +65,6 @@ def [](*args) def key?(key, hash = data) return hash.key?(key) if key.is_a?(Symbol) - # rubocop: disable Lint/DuplicateBranch Schema::Path[key].reduce(hash) do |a, e| if e.is_a?(Array) result = e.all? { |k| key?(k, a) } @@ -81,8 +80,6 @@ def key?(key, hash = data) end a[e] end - # rubocop: enable Lint/DuplicateBranch - true end # rubocop: enable Metrics/PerceivedComplexity From 035f880730c3bacf832cee290db612db18cdb750 Mon Sep 17 00:00:00 2001 From: Brandon Autrey Date: Tue, 10 May 2022 10:54:35 +0300 Subject: [PATCH 2/2] Skip processing `rule.each` on optional value when input is nil When a key has a `maybe` macro, nil values are valid. However, if a `rule.each` is specified on that key, an error is throw saying: ``` `block in each': undefined method `each_with_index' for nil:NilClass (NoMethodError) ``` --- lib/dry/validation/rule.rb | 2 +- spec/unit/rule_spec.rb | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/dry/validation/rule.rb b/lib/dry/validation/rule.rb index bc052675..f51dceed 100644 --- a/lib/dry/validation/rule.rb +++ b/lib/dry/validation/rule.rb @@ -82,7 +82,7 @@ def each(*macros, &block) @keys = [] @block = proc do - unless result.base_error?(root) || !values.key?(root) + unless result.base_error?(root) || !values.key?(root) || values[root].nil? values[root].each_with_index do |_, idx| path = [*Schema::Path[root].to_a, idx] diff --git a/spec/unit/rule_spec.rb b/spec/unit/rule_spec.rb index e91b1853..1aa2e363 100644 --- a/spec/unit/rule_spec.rb +++ b/spec/unit/rule_spec.rb @@ -50,4 +50,24 @@ end end end + + context "with an optional value" do + let(:contract_class) do + Class.new(Dry::Validation::Contract) do + schema do + required(:tags).maybe(:array) + end + end + end + + context "when using .each macro" do + it "does not fail when input is nil" do + contract_class.rule(:tags).each do + key.failure("should not be called") + end + + expect(contract.(tags: nil).errors.to_h).to eq({}) + end + end + end end