5
\$\begingroup\$
if(env['REQUEST_METHOD'] == 'POST')
  $post = {}
  post = env['rack.input'].read.split('&')
  post_split = Array.new
  post.each{|x| post_split << x.split('=')}
  post_split.each{|x|
    $post[x[0]] = x[1]
  }
end

What would be a nice way to do this? I have a string like:

"a=b&c=d"

and i'm trying to get it into a hash like

{:a=>'b',:c=>'d'}

This code works but it is just terrible, and I can't access the keys with

$post[:a] 

only

$post['a']
\$\endgroup\$
5
\$\begingroup\$

The Rack gem has a built-in function to parse the query. If your project depends on rack (e.g. it's a Rails app), then you can use it.

Rack::Utils.parse("a=b&c=d")
# { :a => 'b', :c => 'd' }

If your project doesn't depend on rack, you can copy the method in your code.

DEFAULT_SEP = /[&;] */n

# Stolen from Mongrel, with some small modifications:
# Parses a query string by breaking it up at the '&'
# and ';' characters.  You can also use this to parse
# cookies by changing the characters used in the second
# parameter (which defaults to '&;').
def parse_query(qs, d = nil)
  params = {}

  (qs || '').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p|
    k, v = p.split('=', 2).map { |x| unescape(x) }
    if cur = params[k]
      if cur.class == Array
        params[k] << v
      else
        params[k] = [cur, v]
      end
    else
      params[k] = v
    end
  end

  return params
end
\$\endgroup\$
  • \$\begingroup\$ Seems in the newer versions parse is remove and now one need to call parse_query instead. \$\endgroup\$ – lulalala Jul 24 '14 at 8:03
5
\$\begingroup\$

better way of such parsing is not to reinvent the wheel and use existing ruby functionality

require "cgi"
post = CGI.parse "a=b&c=d"
# => {"a"=>["b"], "c"=>["d"]}

hash values are arrays here, but it makes sense, as you can have several vars in your query string with the same name

for the second part of your question (accessing the keys as symbols) you can use .with_indifferent_access method provided by ActiveSupport (it is already loaded if you use rails)

post.with_indifferent_access[:a]
# => ["b"]
\$\endgroup\$
4
\$\begingroup\$

If you can do without symbol keys, the following builds a Hash without any external dependencies:

s = "a=b&c=d"

Hash[*s.split(/=|&/)] => {"a"=>"b", "c"=>"d"}

\$\endgroup\$
  • \$\begingroup\$ Will fail for "a=b&c=". \$\endgroup\$ – lulalala Jul 24 '14 at 8:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.