Converting nested hash into HTTP url params hash version in Ruby

We cannot send nested hash as a param in HTTP requests. For example, when we would like to send something like this:

{:key => "value", :nested => {:nest => "value"}}

It would be (or should be) mapped like this:

/url/?key=value&nested=%7B%3Anest%3D%3E%5C%22value%5C%22%7D

Doesn't look to good ;) However there is a simple way to convert a nested hash into a params acceptable form. We can convert it to a form, that can be mapped into params like this:

/url/?key=value&nested[nest]=value

Here is method to convert any nested hash to a "one level" equivalent:

  module HashConverter

    def self.encode(value, key = nil, out_hash = {})
      case value
      when Hash  then 
        value.each { |k,v| encode(v, append_key(key,k), out_hash) }
        out_hash
      when Array then 
        value.each { |v| encode(v, "#{key}[]", out_hash) }
        out_hash
      when nil   then ''
      else
        out_hash[key] = value
        out_hash
      end
    end

    private

    def self.append_key(root_key, key)
      root_key.nil? ? :"#{key}" : :"#{root_key}[#{key.to_s}]"
    end

  end

And usage example:

hash = {:level0 => 'value', :nested => {:nest1 => "val1", :nest2 => "val2"}}
HashConverter.encode(hash)
#=> {:level0=>"value", :"nested[nest1]"=>"val1", :"nested[nest2]"=>"val2"}

This form can be easily mapped into a HTTP url params

Categories: Ruby, Software

4 Comments

  1. Actually ActiveSupport has a method that already does that.

    1.9.3-p0 :003 > {:key => “value”, :nested => {:nest => “value”}}.to_param
    => “key=value&nested[nest]=value”

  2. Yup I know. However, not all of us use 1.9.3 and ActiveSupport.

  3. Thanks for this. Looks like I will be adding to Facets as URI.nested_parameters.

  4. awesome men

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Copyright © 2024 Closer to Code

Theme by Anders NorenUp ↑