[ruby] 루비 : 해시를 HTTP 매개 변수로 바꾸는 방법?

평범한 해시와 같이 꽤 쉽습니다.

{: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"}]

도움을 주셔서 감사합니다.



답변

업데이트 : 이 기능은 gem에서 제거되었습니다.

Julien, 당신의 자기 답은 좋은 것입니다, 그리고 나는 그것을 부끄럽게 빌려 왔습니다. 그러나 그것은 예약 된 문자를 제대로 피하지 못하며, 다른 몇 가지 경우가 있습니다.

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


답변

중첩되지 않은 기본 해시의 경우 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


답변

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_formapplication/x-www-form-urlencoded데이터 의 HTML5 정의에 따릅니다 .


답변

부풀린 ActiveSupport를로드하거나 직접 롤링 할 필요가 없으며 Rack::Utils.build_query및 을 사용할 수 있습니다 Rack::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"}]}


답변

Merb에서 훔치기 :

# 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을 참조 하십시오


답변

간단한 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"


답변

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