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']
3 Answers 3
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
-
\$\begingroup\$ Seems in the newer versions
parse
is remove and now one need to callparse_query
instead. \$\endgroup\$lulalala– lulalala2014年07月24日 08:03:28 +00:00Commented Jul 24, 2014 at 8:03
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"]
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"}
-
\$\begingroup\$ Will fail for
"a=b&c="
. \$\endgroup\$lulalala– lulalala2014年07月24日 08:40:50 +00:00Commented Jul 24, 2014 at 8:40