I am writing a unit test, and one of them is returning a zip file and I want to check the content of this zip file, grab some values from it, and pass the values to the next tests.
I'm using Rack Test, so I know the content of my zip file is inside last_response.body
. I have looked through the documentation of RubyZip but it seems that it's always expecting a file. Since I'm running a unit test, I prefer to have everything done in the memory as not to pollute any folder with test zip files, if possible.
See @bronson’s answer for a more up to date version of this answer using the newer RubyZip API.
The Rubyzip docs you linked to look a bit old. The latest release (0.9.9) can handle IO
objects, so you can use a StringIO (with a little tweaking).
Even though the api will accept an IO
, it still seems to assumes it’s a file and tries to call path
on it, so first monkey patch StringIO
to add a path
method (it doesn’t need to actually do anything):
require 'stringio'
class StringIO
def path
end
end
Then you can do something like:
require 'zip/zip'
Zip::ZipInputStream.open_buffer(StringIO.new(last_response.body)) do |io|
while (entry = io.get_next_entry)
# deal with your zip contents here, e.g.
puts "Contents of #{entry.name}: '#{io.read}'"
end
end
and everything will be done in memory.