URLのリクエストパラメータはそのままにしておきたい。
でも、パラメータ全てをリクエストに持たせるのは面倒。
そこで、リファラーのパラメータから拝借してしまおう。という作戦が提案され…
パラメータをハッシュにすればrailsのルーティングヘルパーに渡しやすいかな?
と思った所でタイトル
パラメータに配列がない場合
# require 'uri'
uri = URI::parse(request.referer)
begin
q_array = URI::decode_www_form(uri.query)
q_hash = Hash[q_array]
rescue
q_hash = {}
end
大体はこれでOK。
だけど、配列が混ざると困る。
例えば"tags[]=hoge&tags[]=fuga"
は{"tags[]"=>"fuga"}
となり、
最後のパラメータ以外が欠損する。
パラメータに配列がある場合
# require 'uri'
# require 'rack'
uri = URI::parse(request.referer)
q_hash = Rack::Utils.parse_nested_query(uri.query)
これなら
"tags[]=hoge&tags[]=fuga"
も
{"tags[]"=>["hoge", "fuga"]}
となる。
ついでに
"test[][hash]=1&test[][hash]=2"
は
{"test"=>[{"hash"=>"1"}, {"hash"=>"2"}]}
。
注意事項
-
request.referer
の検査は必要に応じて忘れずに - ルーティングヘルパーが作ったURL文字列にリファラーのパラメータを足すだけで拝借はできる。ハッシュを作る必要はない
# require 'uri'
uri = URI(request.referer)
[xxx_path, uri.query].compact.join('?')
補足
# 文字列 => ハッシュ
Rack::Utils.parse_nested_query("test[][hash]=1&test[][hash]=2") # => {"test"=>[{"hash"=>"1"}, {"hash"=>"2"}]}
Rack::Utils.parse_nested_query("test%5B%5D%5Bhash%5D=1&test%5B%5D%5Bhash%5D=2") # => {"test"=>[{"hash"=>"1"}, {"hash"=>"2"}]}
Rack::Utils.parse_nested_query("test%5B%5D%5Bhash%5D=1&test%5B%5D%5Bhash%5D=%E3%81%82%E3%81%82%E3%81%82") # => {"test"=>[{"hash"=>"1"}, {"hash"=>"あああ"}]}
# ハッシュ => 文字列
Rack::Utils.build_nested_query({"test"=>[{"hash"=>"1"}, {"hash"=>"2"}]}) # => "test[][hash]=1&test[][hash]=2"
Rack::Utils.build_nested_query({"test"=>[{"hash"=>"1"}, {"hash"=>"あああ"}]}) # => "test[][hash]=1&test[][hash]=%E3%81%82%E3%81%82%E3%81%82"
# おまけ
# require 'active_support'
# require 'active_support/core_ext'
{"test"=>[{"hash"=>"1"}, {"hash"=>"2"}]}.to_param # => "test%5B%5D%5Bhash%5D=1&test%5B%5D%5Bhash%5D=2"
{"test"=>[{"hash"=>"1"}, {"hash"=>"あああ"}]}.to_param # => "test%5B%5D%5Bhash%5D=1&test%5B%5D%5Bhash%5D=%E3%81%82%E3%81%82%E3%81%82"
参考文献
[Ruby]URLのクエリ文字列からHashを生成する
How to turn a Ruby Hash into HTTP Params
[GitHub]rack/rack