Zip/Ruby: Zip::ArchiveがGCに回収されるタイミングでclose

Zip/Rubyを使っている人から「Zip::ArchiveがGCに回収されるときに、自動的にcloseしてくれない」というバグ(?)報告が。

正直、closeはユーザの責任でやって欲しいなぁ…

ということで、次のコードを提案してみる。

require 'rubygems'
require 'zipruby'
require 'delegate'

class Foo < DelegateClass(Zip::Archive)
  def initialize(ar)
    super(ar)
    @ar = ar
    ObjectSpace.define_finalizer(self, Foo.mkfnlzr(@ar))
  end

  def self.open(filename, flags = 0)
    ar = Zip::Archive.open(filename, flags)
    retval = nil

    if block_given?
      retval = yield(ar)
      ar.close
    else
      retval = self.new(ar)
    end

    return retval
  end

  def self.mkfnlzr(ar)
    lambda do
      ar.close
      puts 'Zip::Archive closed.'
    end
  end
end

foo = Foo.open('foo.zip')

foo.each do |f|
  puts f.name
end