From c10a3b60985d9fe5a644ef469983d7fded27b40c Mon Sep 17 00:00:00 2001 From: Piotr Solnica Date: Thu, 30 May 2019 10:32:58 +0200 Subject: [PATCH] Fix predicate inference for array with a member Fixes #140 --- lib/dry/schema/macros/key.rb | 2 +- lib/dry/schema/macros/value.rb | 3 +++ spec/integration/schema/type_spec.rb | 18 +++++++++++++++++- .../unit/dry/schema/predicate_inferrer_spec.rb | 8 ++++++++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/dry/schema/macros/key.rb b/lib/dry/schema/macros/key.rb index 53eaa792..305e6f19 100644 --- a/lib/dry/schema/macros/key.rb +++ b/lib/dry/schema/macros/key.rb @@ -55,7 +55,7 @@ def filter(*args, &block) # @api public def value(*args, **opts, &block) extract_type_spec(*args) do |*predicates, type_spec:| - super(*predicates, **opts, &block) + super(*predicates, type_spec: type_spec, **opts, &block) end end diff --git a/lib/dry/schema/macros/value.rb b/lib/dry/schema/macros/value.rb index e58ebdb5..c34ca4b2 100644 --- a/lib/dry/schema/macros/value.rb +++ b/lib/dry/schema/macros/value.rb @@ -33,6 +33,9 @@ def call(*predicates, **opts, &block) raise ArgumentError, 'wrong number of arguments (given 0, expected at least 1)' end + type_spec = opts[:type_spec] + each(type_spec.type.member) if type_spec.respond_to?(:member) + self end diff --git a/spec/integration/schema/type_spec.rb b/spec/integration/schema/type_spec.rb index 90d3714b..15466d95 100644 --- a/spec/integration/schema/type_spec.rb +++ b/spec/integration/schema/type_spec.rb @@ -27,15 +27,31 @@ end context 'single type spec with an array' do + subject(:schema) do + Dry::Schema.Params do + required(:nums).value(:array) + end + end + + it 'infers array? check' do + expect(schema.(nums: nil).errors.to_h).to eql(nums: ['must be an array']) + end + end + + context 'single type spec with an array with a member' do subject(:schema) do Dry::Schema.Params do required(:nums).value(array[:integer]) end end - it 'uses form coercion' do + it 'uses params coercion' do expect(schema.(nums: %w(1 2 3)).to_h).to eql(nums: [1, 2, 3]) end + + it 'infers array? + each(:integer?)' do + expect(schema.(nums: %w(1 oops 3)).errors.to_h).to eql(nums: { 1 => ['must be an integer'] }) + end end context 'sum type spec without rules' do diff --git a/spec/unit/dry/schema/predicate_inferrer_spec.rb b/spec/unit/dry/schema/predicate_inferrer_spec.rb index 4803a77e..dff1fc9d 100644 --- a/spec/unit/dry/schema/predicate_inferrer_spec.rb +++ b/spec/unit/dry/schema/predicate_inferrer_spec.rb @@ -16,6 +16,14 @@ def type(*args) expect(inferrer[type(:string)]).to be(inferrer[type(:string)]) end + it 'returns array? for an array type' do + expect(inferrer[type(:array)]).to eql([:array?]) + end + + it 'returns array? for an array type with member' do + expect(inferrer[type(:array).of(type(:integer))]).to eql([:array?]) + end + it 'returns str? for a string type' do expect(inferrer[type(:string)]).to eql([:str?]) end