diff --git a/lib/sinatra/param.rb b/lib/sinatra/param.rb index 7762b84..3cff53a 100644 --- a/lib/sinatra/param.rb +++ b/lib/sinatra/param.rb @@ -95,8 +95,8 @@ def coerce(param, type, options = {}) return Date.parse(param) if type == Date return Time.parse(param) if type == Time return DateTime.parse(param) if type == DateTime - return Array(param.split(options[:delimiter] || ",")) if type == Array - return Hash[param.split(options[:delimiter] || ",").map{|c| c.split(options[:separator] || ":")}] if type == Hash + return coerce_array(param, options) if type == Array + return Hash[param.to_s.split(options[:delimiter] || ",").map{|c| c.split(options[:separator] || ":")}] if type == Hash return (/(false|f|no|n|0)$/i === param.to_s ? false : (/(true|t|yes|y|1)$/i === param.to_s ? true : nil)) if type == TrueClass || type == FalseClass || type == Boolean return nil rescue ArgumentError @@ -104,6 +104,15 @@ def coerce(param, type, options = {}) end end + ### + # Array is a special case, we should convert from Hash + # or convert to string before parsing. + def coerce_array(param, options = {}) + return param if param.is_a? Array + return param.to_a if param.is_a? Hash + return Array(param.to_s.split(options[:delimiter] || ",")) + end + def validate!(param, options) options.each do |key, value| case key diff --git a/spec/parameter_type_coercion_spec.rb b/spec/parameter_type_coercion_spec.rb index 3db4cbe..133cb83 100644 --- a/spec/parameter_type_coercion_spec.rb +++ b/spec/parameter_type_coercion_spec.rb @@ -117,6 +117,15 @@ expect(parsed_body['arg']).to eq(%w(1 2 3 4 5)) end end + + it 'coerces arrays when hash is given' do + get('/coerce/array', arg: { foo: 'bar', chunky: 'bacon' } ) do |response| + expect(response.status).to eql 200 + parsed_body = JSON.parse(response.body) + expect(parsed_body['arg']).to be_an(Array) + expect(parsed_body['arg']).to eq([['foo', 'bar'], ['chunky', 'bacon']]) + end + end end describe 'Hash' do @@ -128,6 +137,22 @@ expect(parsed_body['arg']).to eq({ 'a' => 'b', 'c' => 'd'}) end end + + it 'coerces hash when non valid arg is given' do + invalid_args = [ + 'not a hash', + ['1', '2', '3'], + 999.99 + ] + + invalid_args.each do |arg| + get('/coerce/hash', arg: arg) do |response| + expect(response.status).to eql 200 + parsed_body = JSON.parse(response.body) + expect(parsed_body['arg']).to be_an(Hash) + end + end + end end describe 'Boolean' do