diff options
-rw-r--r-- | actionpack/CHANGELOG | 2 | ||||
-rwxr-xr-x | actionpack/lib/action_controller/cgi_ext/cgi_methods.rb | 34 | ||||
-rwxr-xr-x | actionpack/test/controller/cgi_test.rb | 15 |
3 files changed, 39 insertions, 12 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index fe0700444d..418fe6fd4d 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Fixed that hashes was not working properly when passed by GET to lighttpd #849 [Nicholas Seckar] + * Fixed assert_template nil will be true when no template was rendered #1565 [maceywj@telus.net] * Added :prompt option to FormOptions#select (and the users of it, like FormOptions#select_country etc) to create "Please select" style descriptors #1181 [Michael Schuerig] diff --git a/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb b/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb index 81bc4867de..c8ed3fb385 100755 --- a/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb +++ b/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb @@ -17,20 +17,19 @@ class CGIMethods #:nodoc: k = CGI.unescape(k) unless k.nil? v = CGI.unescape(v) unless v.nil? - if k =~ /(.*)\[\]$/ - if parsed_params.has_key? $1 - parsed_params[$1] << v - else - parsed_params[$1] = [v] - end - else - parsed_params[k] = v.nil? ? nil : v + keys = split_key(k) + last_key = keys.pop + last_key = keys.pop if (use_array = last_key.empty?) + parent = keys.inject(parsed_params) {|h, k| h[k] ||= {}} + + if use_array then (parent[last_key] ||= []) << v + else parent[last_key] = v end } return parsed_params end - + # Returns the request (POST/GET) parameters in a parsed form where pairs such as "customer[address][street]" / # "Somewhere cool!" are translated into a full hash hierarchy, like # { "customer" => { "address" => { "street" => "Somewhere cool!" } } } @@ -62,6 +61,23 @@ class CGIMethods #:nodoc: end private + + # Splits the given key into several pieces. Example keys are 'name', 'person[name]', + # 'person[name][first]', and 'people[]'. In each instance, an Array instance is returned. + # 'person[name][first]' produces ['person', 'name', 'first']; 'people[]' produces ['people', ''] + def CGIMethods.split_key(key) + if /^([^\[]+)((?:\[[^\]]*\])+)$/ =~ key + keys = [$1] + + keys.concat($2[1..-2].split('][')) + keys << '' if key[-2..-1] == '[]' # Have to add it since split will drop empty strings + + return keys + else + return [key] + end + end + def CGIMethods.get_typed_value(value) if value.respond_to?(:content_type) && !value.content_type.empty? # Uploaded file diff --git a/actionpack/test/controller/cgi_test.rb b/actionpack/test/controller/cgi_test.rb index 1e4bb16337..74f4fc9e8b 100755 --- a/actionpack/test/controller/cgi_test.rb +++ b/actionpack/test/controller/cgi_test.rb @@ -32,7 +32,16 @@ class CGITest < Test::Unit::TestCase CGIMethods.parse_query_parameters(@query_string) ) end - + + def test_deep_query_string + assert_equal({'x' => {'y' => {'z' => '10'}}}, CGIMethods.parse_query_parameters('x[y][z]=10')) + end + + def test_deep_query_string_with_array + assert_equal({'x' => {'y' => {'z' => ['10']}}}, CGIMethods.parse_query_parameters('x[y][z][]=10')) + assert_equal({'x' => {'y' => {'z' => ['10', '5']}}}, CGIMethods.parse_query_parameters('x[y][z][]=10&x[y][z][]=5')) + end + def test_query_string_with_nil assert_equal( { "action" => "create_customer", "full_name" => nil}, @@ -41,10 +50,10 @@ class CGITest < Test::Unit::TestCase end def test_query_string_with_array - assert_equal( + assert_equal( { "action" => "create_customer", "selected" => ["1", "2", "3"]}, CGIMethods.parse_query_parameters(@query_string_with_array) - ) + ) end def test_query_string_with_amps |