Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Provide support for multipart encoding of arrays of hashes that are a…
…rbitrarily nested in other arrays and hashes.
  • Loading branch information
h-lame committed Dec 14, 2012
1 parent dc2b321 commit c98433f
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
8 changes: 6 additions & 2 deletions lib/rack/test/utils.rb
Expand Up @@ -59,7 +59,7 @@ def build_multipart(params, first = true)
if (v.is_a?(Hash))
nested_params = {}
build_multipart(v, false).each { |subkey, subvalue|
nested_params["#{k}[]#{subkey}"] = subvalue
nested_params[subkey] = subvalue
}
flattened_params["#{k}[]"] ||= []
flattened_params["#{k}[]"] << nested_params
Expand Down Expand Up @@ -94,7 +94,11 @@ def build_parts(parameters)
def get_parts(parameters)
parameters.map { |name, value|
if name =~ /\[\]$/ && value.is_a?(Array) && value.all? {|v| v.is_a?(Hash)}
value.map {|v| get_parts(v).join}.join
value.map { |hash|
new_value = {}
hash.each { |k, v| new_value[name+k] = v }
get_parts(new_value).join
}.join
else
if value.respond_to?(:original_filename)
build_file_part(name, value)
Expand Down
20 changes: 20 additions & 0 deletions spec/rack/test/utils_spec.rb
Expand Up @@ -120,6 +120,26 @@
check params["foo"].should == [{"id" => "1", "name" => "Dave"}, {"id" => "2", "name" => "Steve"}]
end

it "builds nested multipart bodies with arbitrarily nested array of hashes" do
files = Rack::Test::UploadedFile.new(multipart_file("foo.txt"))
data = build_multipart("files" => files, "foo" => {"bar" => [{"id" => "1", "name" => 'Dave'},
{"id" => "2", "name" => 'Steve', "qux" => [{"id" => '3', "name" => 'mike'},
{"id" => '4', "name" => 'Joan'}]}]})

options = {
"CONTENT_TYPE" => "multipart/form-data; boundary=#{Rack::Test::MULTIPART_BOUNDARY}",
"CONTENT_LENGTH" => data.length.to_s,
:input => StringIO.new(data)
}
env = Rack::MockRequest.env_for("/", options)
params = Rack::Utils::Multipart.parse_multipart(env)
check params["files"][:filename].should == "foo.txt"
params["files"][:tempfile].read.should == "bar\n"
check params["foo"].should == {"bar" => [{"id" => "1", "name" => "Dave"},
{"id" => "2", "name" => "Steve", "qux" => [{"id" => '3', "name" => 'mike'},
{"id" => '4', "name" => 'Joan'}]}]}
end

it "returns nil if no UploadedFiles were used" do
data = build_multipart("people" => [{"submit-name" => "Larry", "files" => "contents"}])
data.should be_nil
Expand Down

0 comments on commit c98433f

Please sign in to comment.