diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a65883a1f..0874bf395e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ * [#821](https://github.com/intridea/grape/pull/821): Fixed passing string value when hash is expected in params - [@rebelact](https://github.com/rebelact). * [#824](https://github.com/intridea/grape/pull/824): Validate array params against list of acceptable values - [@dnd](https://github.com/dnd). * [#813](https://github.com/intridea/grape/pull/813): Routing methods dsl refactored to get rid of explicit `paths` parameter - [@AlexYankee](https://github.com/AlexYankee). +* [#826](https://github.com/intridea/grape/pull/826): Find coerce_type for Array when not specified - [@manovotn](https://github.com/manovotn). * Your contribution here. 0.9.0 (8/27/2014) diff --git a/lib/grape/validations/params_scope.rb b/lib/grape/validations/params_scope.rb index b3c97ade93..d961809336 100644 --- a/lib/grape/validations/params_scope.rb +++ b/lib/grape/validations/params_scope.rb @@ -97,6 +97,7 @@ def validates(attrs, validations) validations[:coerce] = validations.delete(:type) if validations.key?(:type) coerce_type = validations[:coerce] + doc_attrs[:type] = coerce_type.to_s if coerce_type desc = validations.delete(:desc) || validations.delete(:description) @@ -112,6 +113,8 @@ def validates(attrs, validations) values = values.call if values.is_a?(Proc) + coerce_type = values.first.class if values && coerce_type == Array && !values.empty? + # default value should be present in values array, if both exist if default && values && !values.include?(default) raise Grape::Exceptions::IncompatibleOptionValues.new(:default, default, :values, values) diff --git a/spec/grape/validations/params_scope_spec.rb b/spec/grape/validations/params_scope_spec.rb index 8d4c4e70ef..5be030cab4 100644 --- a/spec/grape/validations/params_scope_spec.rb +++ b/spec/grape/validations/params_scope_spec.rb @@ -24,4 +24,35 @@ def app end end end + + context 'array without coerce type explicitly given' do + + it 'sets the type based on first element' do + subject.params do + requires :periods, type: Array, values: -> { ['day', 'month'] } + end + subject.get('/required') { 'required works' } + + get '/required', periods: ['day', 'month'] + expect(last_response.status).to eq(200) + expect(last_response.body).to eq('required works') + end + + it 'fails to call API without Array type' do + subject.params do + requires :periods, type: Array, values: -> { ['day', 'month'] } + end + subject.get('/required') { 'required works' } + + get '/required', periods: 'day' + expect(last_response.status).to eq(400) + expect(last_response.body).to eq('periods is invalid') + end + + it 'raises exception when values are of different type' do + expect { + subject.params { requires :numbers, type: Array, values: -> { [1, "definitely not a number", 3] } } + }.to raise_error Grape::Exceptions::IncompatibleOptionValues + end + end end