Sinatra(というかRack)で複数の同名パラメータを受け取る
はじめに
http://localhost:4567/?foo=123&foo=456&foo=789
って感じで複数の同名パラメータを送ったら
require 'sinatra' get '/' do params[:foo] #=> 789 end
のように、最後の1つしか取ってくれませんでしたf**k!
そんなわけで、全部取り出すにはどうすればいいのか調べてみました。
結論から言うと
そもそもSinatra(というよりRack)では、複数の同名パラメータを受け取る場合は
http://localhost:4567/?foo[]=123&foo[]=456&foo[]=789
のように、キーの後ろに [] をつけるのが正解のようです。
こうすると、
require 'sinatra' get '/' do params[:foo] #=> ["123", "456", "789"] end
のように、値を配列で取り出すことができます。このあたりはたぶんRailsでも一緒です。
そんなのヤダヤダ、という場合は?
http://localhost:4567/?foo=123&foo=456&foo=789
という形式でパラメータが渡された場合でも同様の動作にするには、
Rack::Utils.parse_query(qs, d = nil)
でパラメータの文字列(上記でいうと foo=123&foo=567&foo=789)をバラしてやればOKです。
パラメータの文字列は、
- GETの場合:
@env['rack.request.query_string']
- POSTの場合:
@env['rack.request.form_vars']
に格納されています。
というわけで、
require 'sinatra' # http://localhost:4567/?foo=123&foo=456&foo=789 でアクセス get '/' do # GETのときは @env['rack.request.query_string'] hoge = Rack::Utils.parse_query(@env['rack.request.query_string']) hoge['foo'] #=> ["123", "456", "789"] end post '/' do # POSTのときは @env['rack.request.form_vars'] hoge = Rack::Utils.parse_query(@env['rack.request.form_vars']) hoge['foo'] #=> ["123", "456", "789"] end
のようにすれば、キーの後ろに [] が無い場合でも複数の同名パラメータを扱えます。
ただし、この場合は
http://localhost:4567/?foo[]=123&foo[]=456&foo[]=789
のように指定されると、キー名が 'foo[]' と解釈されます。
require 'sinatra' # http://localhost:4567/?foo[]=123&foo[]=456&foo[]=789 でアクセス get '/' do hoge = Rack::Utils.parse_query(@env['rack.request.query_string']) hoge['foo'] #=> nil hoge['foo[]'] #=> ["123", "456", "789"] end
まとめ
- Sinatra(というかRack)で複数の同名パラメータを使うときは ?foo[]=1&foo[]=2 みたいにキーの後ろに [] をつける
- Rack::Utils.parse_queryでパラメータの文字列を自前でバラせば ?foo=1&foo=2 みたいなのも扱える