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
January 15, 2012 — 21:12
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”
January 15, 2012 — 21:15
Yup I know. However, not all of us use 1.9.3 and ActiveSupport.
February 3, 2012 — 05:05
Thanks for this. Looks like I will be adding to Facets as URI.nested_parameters.
March 28, 2013 — 21:35
awesome men