9

If I'm turning a ruby hash into a string of name-value pairs (to be used in HTTP params, for example), is this the best way?

# Define the hash
fields = {"a" => "foo", "b" => "bar"}

# Turn it into the name-value string
http_params = fields.map{|k,v| "#{k}=#{v}"}.join('&')

I guess my question is:

Is there an easier way to get to http_params? Granted, the above way works and is fairly straightforward, but I'm curious if there's a way to get from the hash to the string without first creating an array (the result of the map method)?

jerhinesmith
  • 15,214
  • 17
  • 62
  • 89

4 Answers4

11

Rails provides to_query method on Hash class. Try:

fields.to_query

Sergey Glotov
  • 20,200
  • 11
  • 84
  • 98
Anuj Jamwal
  • 111
  • 1
  • 2
8

From the The Pragmatic Programmer's Guide:

Multiple parameters passed to a yield are converted to an array if the block has just one argument.

For example:

> fields = {:a => "foo", :b => "bar"}
> fields.map  { |a| a } # => [[:a, "foo"], [:b, "bar"]]

So your code could be simplified like this:

> fields.map{ |a| a.join('=') }.join('&') # => "a=foo&b=bar"
Christian
  • 81
  • 2
  • 1
    I fail to see how this is simpler. If anything, it hides the intention of the code behind the "multiple parameters => array" magic. – Ben Dec 01 '09 at 06:19
  • Well, it is certainly a matter of taste. *I* find it simpler because it constructs the string without my having to explicitly deal with keys and values. I agree it's less readable, though. – Christian Dec 01 '09 at 07:01
5

This is probably the best you can do. You could iterate through the pairs in the hash, building the string as you go. But in this case the intermediate string would need to be created and deleted at each step.

Do you have a use-case where this is a performance bottleneck? In general Ruby is doing so much work behind the scenes that worrying about a temporary array like this is probably not worth it. If you are concerned that it may be a problem, consider profiling your code for speed and memory usage, often the results are not what you expect.

momeara
  • 1,341
  • 2
  • 17
  • 29
  • No, I'm not worried about it being a performance issue -- I'm just still relatively new to ruby and was curious to see if there was an 'easier' way. Seems every time I start writing a method, I find a ruby or rails method that does exactly the same thing (e.g. `distance_of_time_in_words`). :) – jerhinesmith Dec 01 '09 at 14:16
0

In Rails it also had a method to convert hash to params.

Example1: Turn a hash to params

{ param1: "value1", param2: "value2" }.to_query

Result:

"param1=value1&param2=value2"

Example2: Turn params to hahs

params = "param1=value1&param2=value2"

Rack::Utils.parse_nested_query(params)

Result:

{"param1"=>"value1", "param2"=>"value2"}

Samda
  • 1,439
  • 12
  • 5