-1

I am looking for a function that converts a hash into a query string. I know Rack::Utils.build_query but it use + for spaces.

powerboy
  • 10,523
  • 20
  • 63
  • 93
  • Why does it matter if you use `+` or `%20`? They should be interpreted as the same thing when decoding. – mu is too short Oct 27 '13 at 22:39
  • Think of an api endpoint that requires you to compute a signature based on the query string. – powerboy Oct 27 '13 at 22:50
  • In that case, wouldn't you need to parse the URL, standardize it (so that `?a=b&c=d` and `?c=d&a=b` really do come out the same), and then put it back together? Then your "put it back together" step would standardize on `+` or `%20` for spaces. – mu is too short Oct 28 '13 at 00:27

2 Answers2

0

build_query makes use of Rack::Utils.escape, which replaces spaces with + characters. You could add a version of build_query that makes use of Rack::Utils.escape_path, e.g.

module Rack::Utils
  def your_build_query(params)
    params.map { |k, v|
      if v.class == Array
        build_query(v.map { |x| [k, x] })
      else
        v.nil? ? escape_path(k) : "#{escape_path(k)}=#{escape_path(v)}"
      end
    }.join("&")
  end
end

But all escape_path(s) does is escape(s).gsub('+', '%20'), so you could just call Rack::Utils.build_query(s).gsub('+', '%20').

struthersneil
  • 2,700
  • 10
  • 11
  • It surely works but essentially it does `str.gsub(' ', '+').gsub('+', '%20')` which it is not ideal. – powerboy Oct 27 '13 at 22:51
0

Have you looked at URI::encode_www_form? It's built into Ruby.

From the documentation:

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"

As for the question of using %20 or +, see "When to encode space to plus (+) or %20?".

Community
  • 1
  • 1
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
  • `URI.encode_www_form` is not different from `Rack::Utils.build_query`. "This method doesn’t convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP (ASCII space) to + and converts others to %XX." – powerboy Oct 28 '13 at 01:20