2

I want to create a hash from a querystring. This is my method:

def qs2h(querystring)
  hashes = querystring.split('&').inject({}) do |result,query| 
    k,v = query.split('=')
    if !v.nil?
      result.merge(k.to_sym => v)
    elsif !result.key?(k)
      result.merge(k.to_sym => true)
    else
      result
    end
  end
  hashes
end

qs2h('a=1&b=2&c=3&d') #=> {:a => "1", :b => "2", :c => "3", :d => true}

Is there any simpler method to do this in ruby?

bprayudha
  • 1,034
  • 8
  • 14
  • If you're using rails I would look at this option: http://stackoverflow.com/questions/2772778/parse-string-as-if-it-were-a-querystring-in-ruby-on-rails – Chris Olszewski Feb 24 '14 at 14:52
  • Also if you are not using it :) – mdesantis Feb 24 '14 at 14:55
  • I would suggest you to not symbolize the keys, it can open the door to DoS attacks; that's the reason Rails created `HashWithIndifferentAccess`. I would `require 'activesupport'` and use `HashWithIndifferentAccess` – mdesantis Feb 24 '14 at 15:00
  • In case of a duplicate key, your code does not use the last one as you wrote in a comment to my answer, it will use the first one. So, your code is wrong. – sawa Feb 24 '14 at 15:11
  • @sawa: `qs2h('a=1&b=2&a=3') #=> {:a => 3, :b => 2}` – bprayudha Feb 24 '14 at 15:20
  • I actually overlooked your code. Your `!result.key?(k)` is meaningless. All keys inserted would be symbols, whereas `k` would be a string. So, it would always be evaluated to `true`. In order for it to make any sense, it should be `!result.key?(k.to_sym)`. And once you replace that, then: `qs2h('a=1&b=2&b') #=> {:a => "1", :b => "2"}`. – sawa Feb 24 '14 at 16:16
  • @typ1232 how did you mark this as a duplicate? This question is about Ruby, not Ruby on Rails. The duplicate posted is related to Rails. – dft Mar 01 '17 at 01:20

1 Answers1

7

Use CGI::parse:

CGI.parse('a=1&b=2&c=3&d')
# => {"a"=>["1"], "b"=>["2"], "c"=>["3"], "d"=>[]}
Hash[CGI.parse('a=1&b=2&c=3&d').map {|key,values| [key.to_sym, values[0]||true]}]
# => {:a=>"1", :b=>"2", :c=>"3", :d=>true}
falsetru
  • 357,413
  • 63
  • 732
  • 636