請求參數能夠經過params獲取,params是一個hash對象,包括GET、POST、PUT參數,以及路徑字符串中的任何命名參數:git
get :public_timeline do Status.order(params[:sort_by]) end
Parameters are automatically populated from the request body on POST and PUT for form input, JSON and XML content-types.
請求:正則表達式
curl -d '{"text": "140 characters"}' 'http://localhost:9292/statuses' -H Content-Type:application/json -v
Grape中:json
post '/statuses' do Status.create!(text: params[:text]) end
多部分的POSTs和PUTs也是支持的。
請求:數組
curl --form image_file='@image.jpg;type=image/jpg' http://localhost:9292/upload
Grape中:app
post 'upload' do # file in params[:image_file] end
在如下任何一個或兩個有衝突時:less
Grape只容許訪問在params塊中聲明的變量,它過濾掉傳遞過來可是不容許訪問的變量,請看下面的API:dom
format :json post 'users/signup' do { 'declared_params' => declared(params) } end
若是咱們沒有指定任何參數,declared會返回一個空的Hashie::Mash實例。
請求:curl
curl -X POST -H "Content-Type: application/json" localhost:9292/users/signup -d '{"user": {"first_name":"first name", "last_name": "last name"}}'
應答:ide
{ "declared_params": {} }
一旦咱們添加了參數requirements,Grape僅返回聲明的參數:post
format :json params do requires :user, type: Hash do requires :first_name, type: String requires :last_name, type: String end end post 'users/signup' do { 'declared_params' => declared(params) } end
請求:
curl -X POST -H "Content-Type: application/json" localhost:9292/users/signup -d '{"user": {"first_name":"first name", "last_name": "last name", "random": "never shown"}}'
應答:
{ "declared_params": { "user": { "first_name": "first name", "last_name": "last name" } } }
返回的hash是Hashie::Mash實例,容許你使用.訪問參數:
declared(params).user == declared(params)['user']
The #declared method is not available to before filters, as those are evaluated prior to parameter coercion.
默認的,declared(params)包含了在父命名空間中聲明的參數,若是你只向返回當前命名空間的參數,能夠把include_parent_namespaces選項設置爲false。
format :json namespace :parent do params do requires :parent_name, type: String end namespace ':parent_name' do params do requires :child_name, type: String end get ':child_name' do { 'without_parent_namespaces' => declared(params, include_parent_namespaces: false), 'with_parent_namespaces' => declared(params, include_parent_namespaces: true), } end end end
請求:
curl -X GET -H "Content-Type: application/json" localhost:9292/parent/foo/bar
應答:
{ "without_parent_namespaces": { "child_name": "bar" }, "with_parent_namespaces": { "parent_name": "foo", "child_name": "bar" }, }
默認的,declared(params)包含值爲nil的參數,若是你只想返回值爲非nil的參數,你可使用include_missing 選項。該選項默認爲true,看下下面的API:
format :json params do requires :first_name, type: String optional :last_name, type: String end post 'users/signup' do { 'declared_params' => declared(params, include_missing: false) } end
請求:
curl -X POST -H "Content-Type: application/json" localhost:9292/users/signup -d '{"user": {"first_name":"first name", "random": "never shown"}}'
include_missing:false時:
{ "declared_params": { "user": { "first_name": "first name" } } }
include_missing:true時:
{ "declared_params": { "first_name": "first name", "last_name": null } }
在嵌套的hash中也會生效:
format :json params do requires :user, type: Hash do requires :first_name, type: String optional :last_name, type: String requires :address, type: Hash do requires :city, type: String optional :region, type: String end end end post 'users/signup' do { 'declared_params' => declared(params, include_missing: false) } end
請求:
curl -X POST -H "Content-Type: application/json" localhost:9292/users/signup -d '{"user": {"first_name":"first name", "random": "never shown", "address": { "city": "SF"}}}'
include_missing:false時:
{ "declared_params": { "user": { "first_name": "first name", "address": { "city": "SF" } } } }
include_missing:true時
{ "declared_params": { "user": { "first_name": "first name", "last_name": null, "address": { "city": "Zurich", "region": null } } } }
注意,值被設置爲nil的變量和缺失是不一樣的,include_missing被設置爲false時,值爲nil的變量也會返回。
請求:
curl -X POST -H "Content-Type: application/json" localhost:9292/users/signup -d '{"user": {"first_name":"first name", "last_name": null, "address": { "city": "SF"}}}'
include_missing:false時的應答:
{ "declared_params": { "user": { "first_name": "first name", "last_name": null, "address": { "city": "SF"} } } }
你能夠經過一個params block爲參數定義校驗選項:
params do requires :id, type: Integer optional :text, type: String, regexp: /\A[a-z]+\z/ group :media do requires :url end optional :audio do requires :format, type: Symbol, values: [:mp3, :wav, :aac, :ogg], default: :mp3 end mutually_exclusive :media, :audio end put ':id' do # params[:id] is an Integer end
若是指定了參數類型,在參數強轉後,會對強轉後的參數進行隱式的校驗,以保證轉換後的類型是聲明的類型。(When a type is specified an implicit validation is done after the coercion to ensure the output type is the one declared.)
可選參數能夠提供一個默認值:
params do optional :color, type: String, default: 'blue' optional :random_number, type: Integer, default: -> { Random.rand(1..100) } optional :non_random_number, type: Integer, default: Random.rand(1..100) end
注意,默認值要知足全部的校驗條件,若是沒有顯示提供值,下面的例子老是會失敗:
params do optional :color, type: String, default: 'blue', values: ['red', 'green'] end
除了上面列出的類型,若是提供了顯示的轉換方法parse,任何類均可以當作類型使用。若是提供的是類方法,Grape會自動使用,該方法入參必須是一個字符串,而且返回一個正確的類型,或者拋出異常表示該值無效:
class Color attr_reader :value def initialize(color) @value = color end def self.parse(value) fail 'Invalid color' unless %w(blue red green).include?(value) new(value) end end # ... params do requires :color, type: Color, default: Color.new('blue') end get '/stuff' do # params[:color] is already a Color. params[:color].value end
另外,經過coerce_with能夠爲任意類型提供自定義的轉換方法,任何實現了parse或者call方法的類或對象均可以,該方法必須接受一個字符串參數,返回類型必須可以和type給出的匹配:
params do requires :passwd, type: String, coerce_with: Base64.method(:decode) requires :loud_color, type: Color, coerce_with: ->(c) { Color.parse(c.downcase) } requires :obj, type: Hash, coerce_with: JSON do requires :words, type: Array[String], coerce_with: ->(val) { val.split(/\s+/) } optional :time, type: Time, coerce_with: Chronic end end
下面的例子爲corece_with提供了一個lambda表達式,該表達式接受一個string類型參數,返回一個整形數組,以匹配Array[Integer]類型:
params do requires :values, type: Array[Integer], coerce_with: ->(val) { val.split(/\s+/).map(&:to_i) } end
Grape利用Rack::Request內置的對MultipatFile參數的支持,這種類型的參數能夠被聲明爲type: File:
params do requires :avatar, type: File end post '/' do # Parameter will be wrapped using Hashie: params.avatar.filename # => 'avatar.png' params.avatar.type # => 'image/png' params.avatar.tempfile # => #<File> end
Grape支持JSON格式的複雜類型參數,使用type: JSON聲明,JSON對象和數組均可以被接受,在兩種狀況下,內置的校驗規則對全部的對象(JSON對象或JSON數組中的全部對象)都適用。(Grape supports complex parameters given as JSON-formatted strings using the special type: JSON declaration. JSON objects and arrays of objects are accepted equally, with nested validation rules applied to all objects in either case):
params do requires :json, type: JSON do requires :int, type: Integer, values: [1, 2, 3] end end get '/' do params[:json].inspect end # ... client.get('/', json: '{"int":1}') # => "{:int=>1}" client.get('/', json: '[{"int":"1"}]') # => "[{:int=>1}]" client.get('/', json: '{"int":4}') # => HTTP 400 client.get('/', json: '[{"int":4}]') # => HTTP 400
另外,也可使用type: Array[JSON],用以明確表示被傳遞進來的參數是一個數組,若是隻傳遞進來的是非數組形式的單個對象,會將其轉換成數組。
params do requires :json, type: Array[JSON] do requires :int, type: Integer end end get '/' do params[:json].each { |obj| ... } # always works end
For stricter control over the type of JSON structure which may be supplied, use type: Array, coerce_with: JSON or type: Hash, coerce_with: JSON.
多類型參數可使用types來聲明,而不是使用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"]
做爲一個特例,經過傳遞包含多個成員的Set或者Array給type,能夠聲明多成員類型:
params do requires :status_codes, type: Array[Integer,String] end get '/' do params[:status_codes].inspect end # ... client.get('/', status_codes: %w(1 two)) # => [1, "two"]
經過group或者爲requires或者optinal提供block可使用嵌套參數:
params do requires :id, type: Integer optional :text, type: String, regexp: /\A[a-z]+\z/ group :media do requires :url end optional :audio do requires :format, type: Symbol, values: [:mp3, :wav, :aac, :ogg], default: :mp3 end mutually_exclusive :media, :audio end put ':id' do # params[:id] is an Integer end
上面例子的意思是,須要同時提供params[:media][:url]
和 params[:id]
,提供params[:audio]
時才須要提供params[:audio][:format]
。提供block時,group、requires、optional接受值能夠是Array或者Hash的type(默認爲Array)。Depending on the value, the nested parameters will be treated either as values of a hash or as values of hashes in an array.
params do optional :preferences, type: Array do requires :key requires :value end requires :name, type: Hash do requires :first_name requires :last_name end end
對於給定一個參數時,必須提供另外一個參數的狀況,可使用given方法:
params do optional :shelf_id, type: Integer given :shelf_id do requires :bin_id, type: Integer end end
在上面的例子中,Grape會使用blank?方法檢查是否提供了shelf_id參數。
give也接受一個自定義的Proc,下面的例子,description參數只有在category 的值是「foo」的時候才須要提供:
params do optional :category given category: ->(val) { val == 'foo' } do requires :description end end
參數定義中也可使用allow_blank,用以保證參數有值。默認狀況下,requires只檢查請求中包含了指定的參數,可是忽略它的值,經過指定allow_blank: false,空值和只包含空白符的值將是無效的。
allow_blank能夠和requires/optional結合使用,若是參數是必須的,那麼就必須包含一個值;若是是可選的,那麼請求中若是含有這個參數時,它的值必須不能是空字符串或者空白符。
params do requires :username, allow_blank: false optional :first_name, allow_blank: false end
經過:values選項,參數能夠被限制爲一組特定的值。
Default values are eagerly evaluated. Above :non_random_number will evaluate to the same number for each call to the endpoint of this params block. To have the default evaluate lazily with each request use a lambda, like :random_number above.
params do requires :status, type: Symbol, values: [:not_started, :processing, :done] optional :numbers, type: Array[Integer], default: 1, values: [1, 2, 3, 5, 8] end
能夠給:values選項提供一個範圍參數:
params do requires :latitude, type: Float, values: -90.0..+90.0 requires :longitude, type: Float, values: -180.0..+180.0 optional :letters, type: Array[String], values: 'a'..'z' end
注意,range的起始值類型必須和:type指定的匹配(若是沒有提供:type選項,結束值的類型和開始值的類型必須相同),下面的例子是非法的:
params do requires :invalid1, type: Float, values: 0..10 # 0.kind_of?(Float) => false optional :invalid2, values: 0..10.0 # 10.0.kind_of?(0.class) => false end
也能夠給:values選項提供一個Proc對象,在每一個請求中進行求值:
params do requires :hashtag, type: String, values: -> { Hashtag.all.map(&:tag) } end
也能夠經過except選項來限制不能包含哪些值,except接受相同類型的參數做爲值(Procs, ranges,等):
params do requires :browsers, values: { except: [ 'ie6', 'ie7', 'ie8' ] } end
values和except能夠結合使用,用以指定哪些值能接受,哪些不能接受。能夠分別爲except和value自定義不一樣的錯誤消息,用於指定值落在了except中或者不在value中:
params do requires :number, type: Integer, values: { value: 1..20 except: [4,13], except_message: 'includes unsafe numbers', message: 'is outside the range of numbers allowed' } end
經過:regexp選項,能夠將參數限制爲和正則表達式匹配,若是不匹配將會返回一個錯誤,正則表達式選項對requires和optinal參數都有效。
params do requires :email, regexp: /.+@.+/ end
當參數不包含值時,校驗是能經過的。爲了保證參數包含值,可使用alow_blank: false。
params do requires :email, allow_blank: false, regexp: /.+@.+/ end
參數能夠經過mutually_exclusive定義爲互斥,保證不會出如今同一個請求中:
params do optional :beer optional :wine mutually_exclusive :beer, :wine end
能夠定義多組:
params do optional :beer optional :wine mutually_exclusive :beer, :wine optional :scotch optional :aquavit mutually_exclusive :scotch, :aquavit end
警告:永遠不要將兩個必須的參數設置爲互斥,不然將致使參數永遠無效;一個必須的參數和一個可選的參數互斥,會致使後一個參數用於無效
經過exactly_one_of能夠指定正好有一個參數被提供:
params do optional :beer optional :wine exactly_one_of :beer, :wine end
at_least_one_of選項保證至少有一個參數被提供:
params do optional :beer optional :wine optional :juice at_least_one_of :beer, :wine, :juice end
能夠經過all_or_none_of選項指定全部參數都提供或都不提供。
params do optional :beer optional :wine optional :juice all_or_none_of :beer, :wine, :juice end
全部的這些方法都一個在任何嵌套層使用:
params do requires :food do optional :meat optional :fish optional :rice at_least_one_of :meat, :fish, :rice end group :drink do optional :beer optional :wine optional :juice exactly_one_of :beer, :wine, :juice end optional :dessert do optional :cake optional :icecream mutually_exclusive :cake, :icecream end optional :recipe do optional :oil optional :meat all_or_none_of :oil, :meat end end
命名空間容許在每一個方法中經過命名空間定義和使用參數。
namespace :statuses do params do requires :user_id, type: Integer, desc: 'A user ID.' end namespace ':user_id' do desc "Retrieve a user's status." params do requires :status_id, type: Integer, desc: 'A status ID.' end get ':status_id' do User.find(params[:user_id]).statuses.find(params[:status_id]) end end end
namespace方法有好幾個別名,包括:group, resource, resources, and segment。你能夠選擇一個你喜歡的。
經過route_param你能夠方便的定義一個路由參數做爲命名空間:
namespace :statuses do route_param :id do desc 'Returns all replies for a status.' get 'replies' do Status.find(params[:id]).replies end desc 'Returns a status.' get do Status.find(params[:id]) end end end
You can also define a route parameter type by passing to route_param's options.
namespace :arithmetic do route_param :n, type: Integer do desc 'Returns in power' get 'power' do params[:n] ** params[:n] end end end