Grape自定义参数类型
Grape的params
函数是非常方便用于定义API参数的工具. 这次做到一个接口要传入GeoJSON格式的参数. 与世界在接口上直接写了:
params do
requires :location, type: GeoJSONPoint, desc: "地点"
end
class GeoJSONPoint
attr_accessor :type, :coordinates
def initialize(coordinates=[])
@coordinates = coordinates
end
# always a point
def type
"Point"
end
end
不过这样显然是不行的, 一定会出400 Bad Request. Grape毕竟不知道GeoJSONPoint这个类是怎么转换的. 读了读Grape的代码, 发现Grape是用 Virtus 这个gem来转换参数=>对象的.
于是这个GeoJSONPoint的类就需要用Virtus的方式来定义. 于是代码变成了
class GeoJSONPoint
include Virtus.model
attribute :type, String
attribute :coordinates, Array
def initialize(coordinates=[])
@coordinates = coordinates
end
# always a point
def type
"Point"
end
end
先用Virtus的方法试一下, 结果OK:
coercer = Virtus::Attribute.build(GeoJSONPoint)
point = coercer.coerce({type: "Point", coordinates: [190, 50]})
=> #<GeoJSONPoint:0x007ffdf3a61618 @coordinates={:type=>"Point", :coordinates=>[190, 50]}>
再到RestClient里发个请求看看:
{"location" : {
"type" : "Point",
"coordinates" : [190, 50]
}}
结果:
{
"application":{"name":"TestServer","status":"ok"},
"request":{
"headers":{
"Version":"HTTP/1.1",
"Host":"localhost:3000",
"Connection":"Keep-Alive",
"User-Agent":"Apache-HttpClient/4.3.5 (java 1.5)",
"Accept-Encoding":"gzip,deflate"
},
"params":{
"location":{
"type":"Point",
"coordinates":[190,50]}}},
"env":"127.0.0.1"
}
Grape能够成功把GeoJSONPoint转换出来.