220

これは、次のような単純なハッシュを使用すると非常に簡単です。

{:a => "a", :b => "b"} 

これは次のように変換されます

"a=a&b=b"

しかし、あなたは次のようなもっと複雑なもので何をしますか

{:a => "a", :b => ["c", "d", "e"]} 

これは次のように変換されます

"a=a&b[0]=c&b[1]=d&b[2]=e" 

またはさらに悪いことに、(何をすべきか)次のようなもので:

{:a => "a", :b => [{:c => "c", :d => "d"}, {:e => "e", :f => "f"}]

それで大いに感謝された助けをありがとう!

4

14 に答える 14

294

ネストされていない基本的なハッシュの場合、Rails/ActiveSupport にはObject#to_query.

>> {:a => "a", :b => ["c", "d", "e"]}.to_query
=> "a=a&b%5B%5D=c&b%5B%5D=d&b%5B%5D=e"
>> CGI.unescape({:a => "a", :b => ["c", "d", "e"]}.to_query)
=> "a=a&b[]=c&b[]=d&b[]=e"

http://api.rubyonrails.org/classes/Object.html#method-i-to_query

于 2010-09-30T17:32:36.477 に答える
168

Ruby 1.9.2 以降を使用しているURI.encode_www_form場合、配列が必要ない場合に使用できます。

例 (1.9.3 の Ruby ドキュメントから):

URI.encode_www_form([["q", "ruby"], ["lang", "en"]])
#=> "q=ruby&lang=en"
URI.encode_www_form("q" => "ruby", "lang" => "en")
#=> "q=ruby&lang=en"
URI.encode_www_form("q" => ["ruby", "perl"], "lang" => "en")
#=> "q=ruby&q=perl&lang=en"
URI.encode_www_form([["q", "ruby"], ["q", "perl"], ["lang", "en"]])
#=> "q=ruby&q=perl&lang=en"

配列値は[]、クエリ文字列で慣れ親しんだようなキー名で設定されていないことに気付くでしょう。使用する仕様encode_www_formはHTML5のデータ定義に準拠していapplication/x-www-form-urlencodedます。

于 2012-06-28T19:35:42.760 に答える
90

更新:この機能は gem から削除されました。

ジュリアン、あなたの自己回答は良いものです。私は恥知らずにそれを借りてきましたが、予約文字を適切にエスケープせず、それが壊れるいくつかのエッジケースがあります.

require "addressable/uri"
uri = Addressable::URI.new
uri.query_values = {:a => "a", :b => ["c", "d", "e"]}
uri.query
# => "a=a&b[0]=c&b[1]=d&b[2]=e"
uri.query_values = {:a => "a", :b => [{:c => "c", :d => "d"}, {:e => "e", :f => "f"}]}
uri.query
# => "a=a&b[0][c]=c&b[0][d]=d&b[1][e]=e&b[1][f]=f"
uri.query_values = {:a => "a", :b => {:c => "c", :d => "d"}}
uri.query
# => "a=a&b[c]=c&b[d]=d"
uri.query_values = {:a => "a", :b => {:c => "c", :d => true}}
uri.query
# => "a=a&b[c]=c&b[d]"
uri.query_values = {:a => "a", :b => {:c => "c", :d => true}, :e => []}
uri.query
# => "a=a&b[c]=c&b[d]"

宝石は「アドレス指定可能」です

gem install addressable
于 2009-04-29T16:00:12.833 に答える
68

肥大化した ActiveSupport をロードしたり、独自のものを展開したりする必要はありませRack::Utils.build_queryRack::Utils.build_nested_query。良い例を示すブログ投稿を次に示します。

require 'rack'

Rack::Utils.build_query(
  authorization_token: "foo",
  access_level: "moderator",
  previous: "index"
)

# => "authorization_token=foo&access_level=moderator&previous=index"

配列も処理します。

Rack::Utils.build_query( {:a => "a", :b => ["c", "d", "e"]} )
# => "a=a&b=c&b=d&b=e"
Rack::Utils.parse_query _
# => {"a"=>"a", "b"=>["c", "d", "e"]}

または、より難しいネストされたもの:

Rack::Utils.build_nested_query( {:a => "a", :b => [{:c => "c", :d => "d"}, {:e => "e", :f => "f"}] } )
# => "a=a&b[][c]=c&b[][d]=d&b[][e]=e&b[][f]=f"
Rack::Utils.parse_nested_query _
# => {"a"=>"a", "b"=>[{"c"=>"c", "d"=>"d", "e"=>"e", "f"=>"f"}]}
于 2013-01-08T19:24:25.190 に答える
12

単純な ASCII キー/値クエリ文字列のみをサポートする必要がある場合は、短くてわかりやすいワンライナーを次に示します。

hash = {"foo" => "bar", "fooz" => 123}
# => {"foo"=>"bar", "fooz"=>123}
query_string = hash.to_a.map { |x| "#{x[0]}=#{x[1]}" }.join("&")
# => "foo=bar&fooz=123"
于 2013-06-05T13:54:24.660 に答える
10

マーブから盗む:

# File merb/core_ext/hash.rb, line 87
def to_params
  params = ''
  stack = []

  each do |k, v|
    if v.is_a?(Hash)
      stack << [k,v]
    else
      params << "#{k}=#{v}&"
    end
  end

  stack.each do |parent, hash|
    hash.each do |k, v|
      if v.is_a?(Hash)
        stack << ["#{parent}[#{k}]", v]
      else
        params << "#{parent}[#{k}]=#{v}&"
      end
    end
  end

  params.chop! # trailing &
  params
end

http://noobkit.com/show/ruby/gems/development/merb/hash/to_params.htmlを参照してください

于 2009-04-28T16:24:04.187 に答える
5
class Hash
  def to_params
    params = ''
    stack = []

    each do |k, v|
      if v.is_a?(Hash)
        stack << [k,v]
      elsif v.is_a?(Array)
        stack << [k,Hash.from_array(v)]
      else
        params << "#{k}=#{v}&"
      end
    end

    stack.each do |parent, hash|
      hash.each do |k, v|
        if v.is_a?(Hash)
          stack << ["#{parent}[#{k}]", v]
        else
          params << "#{parent}[#{k}]=#{v}&"
        end
      end
    end

    params.chop! 
    params
  end

  def self.from_array(array = [])
    h = Hash.new
    array.size.times do |t|
      h[t] = array[t]
    end
    h
  end

end
于 2009-04-28T17:06:17.770 に答える
3

これは古い質問であることは知っていますが、このタスクを実行するための単純な宝石が見つからなかったため、このコードを投稿したかっただけです。

module QueryParams

  def self.encode(value, key = nil)
    case value
    when Hash  then value.map { |k,v| encode(v, append_key(key,k)) }.join('&')
    when Array then value.map { |v| encode(v, "#{key}[]") }.join('&')
    when nil   then ''
    else            
      "#{key}=#{CGI.escape(value.to_s)}" 
    end
  end

  private

  def self.append_key(root_key, key)
    root_key.nil? ? key : "#{root_key}[#{key.to_s}]"
  end
end

ここで宝石としてロールアップ: https://github.com/simen/queryparams

于 2011-10-29T19:06:14.570 に答える
0

私はこの宝石を使うのが好きです:

https://rubygems.org/gems/php_http_build_query

使用例:

puts PHP.http_build_query({"a"=>"b","c"=>"d","e"=>[{"hello"=>"world","bah"=>"black"},{"hello"=>"world","bah"=>"black"}]})

# a=b&c=d&e%5B0%5D%5Bbah%5D=black&e%5B0%5D%5Bhello%5D=world&e%5B1%5D%5Bbah%5D=black&e%5B1%5D%5Bhello%5D=world
于 2015-04-03T23:13:38.110 に答える