Grape: Parameters with multiple types fail validation

Created on 18 Mar 2016  路  4Comments  路  Source: ruby-grape/grape

I'm seeing validation fail on Grape 0.15.0 for parameters which allow multiple types, as shown by the test case below. Replacing [Integer,String] with simply String or Integer works when provided the relevant format.

require 'grape'

class TestAPI < Grape::API
  params do
    # We originally saw the problem on a JSON parameter, so ensure it applies both on
    # that and a normal parameter.
    requires :message, type: JSON do
      requires :id, type: [Integer,String]
    end
    requires :id, type: [Integer,String]
  end
  post do
    status 200
    { message_id: params[:message][:id], id: params[:id] }
  end
end

run TestAPI

This request will return message[id] is invalid, id is invalid.

POST  HTTP/1.1
Host: localhost:9292
Content-Type: application/json
Cache-Control: no-cache

{
    "message": "{ \"id\": \"12\" }",
    "id": "12"
}
feature request

Most helpful comment

Am I misreading this when I say that type: <multiple things> is simply not supported and should error?

All 4 comments

I eventually tracked the problem down to using type rather than types.

While that's clearly user error, and in some ways makes sense, I think its quite easy to miss - is there any way this could be supported without using a different option key?

Yes, would be good to improve this, PR welcome please!

@jellybob @dblock
I don't know if this change is possible. There is distinction between type and types for a purpose. We can have a field with multiple types or a collection with variant type. This behavior is described here

Multiple Allowed Types

Variant-type parameters can be declared using the types option rather than type:

params do
  requires :status_code, types: [Integer, String, Array[Integer, String]]
end
get '/' do
  params[:status_code].inspect
end

# ...

client.get('/', status_code: 'OK_GOOD') # => "OK_GOOD"
client.get('/', status_code: 300) # => 300
client.get('/', status_code: %w(404 NOT FOUND)) # => [404, "NOT", "FOUND"]

As a special case, variant-member-type collections may also be declared, by
passing a Set or Array with more than one member to type:

```ruby
params do
requires :status_codes, type: Array[Integer,String]
end
get '/' do
params[:status_codes].inspect
end

It would be impossible to guess whether we want a collection or multiple types when we merge those concepts into single keyword. Am I correct?

One way to achieve that is to introduce new type e.g Collection

for fields with multiple types

params do
  requires :id, type: [Integer,String]
end

for collections with variant types

params do
  requires :ids, type: Collection[Integer, String]
end

But I'm not sure if this is better than types.

Am I misreading this when I say that type: <multiple things> is simply not supported and should error?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dblock picture dblock  路  6Comments

stabenfeldt picture stabenfeldt  路  6Comments

jereynolds picture jereynolds  路  5Comments

yanguango picture yanguango  路  8Comments

Legogris picture Legogris  路  6Comments