From a3b32affd85ed071b02a148c0dc0fe43f9d4967d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Busqu=C3=A9?= Date: Wed, 15 Jan 2020 18:09:26 +0100 Subject: [PATCH] Fix macros expecting a range as option References #608 --- lib/dry/validation/rule.rb | 7 +++++- spec/integration/macros/custom_macros_spec.rb | 25 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/dry/validation/rule.rb b/lib/dry/validation/rule.rb index e83f5403..b323a99f 100644 --- a/lib/dry/validation/rule.rb +++ b/lib/dry/validation/rule.rb @@ -118,7 +118,12 @@ def parse_macros(*args) args.each_with_object([]) do |spec, macros| case spec when Hash - spec.each { |k, v| macros << [k, Array(v)] } + spec.each do |k, v| + macros << [ + k, + v.is_a?(Array) ? v : [v] + ] + end else macros << Array(spec) end diff --git a/spec/integration/macros/custom_macros_spec.rb b/spec/integration/macros/custom_macros_spec.rb index c5f1cc70..6b1f5ef5 100644 --- a/spec/integration/macros/custom_macros_spec.rb +++ b/spec/integration/macros/custom_macros_spec.rb @@ -79,4 +79,29 @@ class Test::BaseContract < Dry::Validation::Contract; end .to eql(numbers: ['must have at least 3 items']) end end + + context 'using a macro with a range option' do + before do + Test::BaseContract.register_macro(:in_range) do |macro:| + range = macro.args[0] + + all_included_in_range = value.all? { |elem| range.include?(elem) } + key.failure("every item must be included in #{range}") unless all_included_in_range + end + + contract_class.rule(:numbers).validate(in_range: 1..3) + end + + after do + Test::BaseContract.macros._container.delete('in_range') + end + + it 'succeeds with valid input' do + expect(contract.(numbers: [1, 2, 3])).to be_success + end + + it 'fails with invalid input' do + expect(contract.(numbers: [1, 2, 6])).to be_failure + end + end end