RailsでURLのクエリ文字列を組み立てるときはHash#to_queryを使うと捗る
はじめに
Railsでコードを書いていて、ControllerやhelperでURLのクエリ文字列を組み立てる場面ってありますよね。
こうゆうとき、僕は今まで
query = { hoge: 1, fuga: 2 } query.map{ |k,v| "#{k}=#{v}" }.join("&")
とかやってたんですけど、これだと値が配列の場合に対応してないんですよね。。。
で、もっといいやり方ないかなって探してみたら見つけたので紹介します。
Hash#to_query
Hash#to_query
はActiveSupportのHash拡張で、レシーバーのHashインスタンスから、クエリ文字列を組み立てて返してくれます。
Hash#to_param
も同様の挙動です。より正確に言うと、Hash#to_query
がHash#to_param
のエイリアスです。
実行例
require 'active_support/core_ext' { hoge: 1, fuga: 2 }.to_query # => "fuga=2&hoge=1" # 何気にアルファベット順になっているのもポイント。 { hoge: [0,1], fuga: { piyo: 2 } }.to_query # => "fuga%5Bpiyo%5D=2&hoge%5B%5D=0&hoge%5B%5D=1" # 配列や入れ子のハッシュにも対応。エスケープもしてくれる。 { id: 1, name: "hoge" }.to_query("user") # => "user%5Bid%5D=1&user%5Bname%5D=hoge" # 引数に文字列(Symbolでも可)を渡すと、名前空間付きになる。
元コード読むのも勉強になる
「たぶん再帰的にto_query
を呼び出しているんだろうな」という予測はつくと思うんですが、実際はもう少し工夫されています。
なかなか勉強になったので、よかったらどう実装されているかチェックしてみてください。
- rails/activesupport/lib/active_support/core_ext/object/to_param.rb
- rails/activesupport/lib/active_support/core_ext/object/to_query.rb
個人的には、Hash#to_param
内のcollect do |key, value| ~ end.sort! * '&'
という記述にびっくりしました。*1
おわりに
Railsは、こうゆうのないかな〜って思って探してみるとだいたいあるので便利。