Subscribe to my Feed, follow me on Twitter, recommend me on Working With Rails or see my code on GitHub
Zippy: rubyzip for dummies
Ok, so I had to dynamically create zip files the other day. No biggie, rubyzip handles that very well. It’s just that 90% of the time it took was spent reading through the docs to figure out exactly which spells I had to cast to make it do what I wanted. And I’ve done it before, too. Now, it says right there on the first page – almost like a disclaimer – that “the basic API is modeled after the classes in java.util.zip from the Java SDK”, but seeing things like ZipOutputStream and ZipStreamableStream gives me flashbacks to Programming 101 and travelling salesmen; why couldn’t it be more like, say, Hash? This is Ruby damnit, we don’t actually want to program, we want to tell the computer what to do and then it just does it. Kind of like this:
Zippy.create 'funny.zip' do |zip|
zip['README'] = 'Fun pics 4 u'
Dir['pictures/*.jpg'].each do |filename|
zip[filename] = File.open(filename)
end
end
You can probably guess by now that I’m not just making this stuff up as I go. Zippy is a (thin) wrapper around rubyzip which has a more Ruby-like interface. It happily ignores edge cases – you know, like handling directories – and focuses on the most common operations.
Zippy.open 'funny.zip' do |zip|
log "Changing README, was \"#{zip['README']}\""
zip['README'] = 'Amusing photographs of cats'
end
Zippy.create('reports.zip', 'report.pdf' => generate_pdf, 'README' => 'Latest reports')
puts Zippy['reports.zip', 'README']
Zippy['reports.zip', 'another_report.pdf'] = generate_another_pdf
One of the things I had to deal with was having to give rubyzip a filename, although I wasn’t going to save the file to disk but send it as a response to a request in a Rails app. Zippy doesn’t need an explicit filename (it will still save it to a temporary file):
Zippy.new('foo.txt' => 'bar').data
In fact, if you add it as a gem dependency in your Rails app,
config.gem "zippy", :source => "http://gems.github.com", :lib => "zippy"
it has a little plugin which registers a template handler for the extension zipper, so you can generate zips on the fly:
#galleries_ontroller.rb
class GalleriesController < ActionController::Base
def show
@gallery = Gallery[params[:id]]
respond_to do |format|
format.html
format.zip
end
end
end
#galleries/show.zip.zipper
zip['gallery.txt'] = "#{@gallery.title}\n\n#{@gallery.description}"
@gallery.photos.each do |photo|
zip["photos/#{photo.to_param}.jpg"] = File.open(photo.filename)
end
