RubyのTempfile.createが便利

Tempfileの実装を調べようとCRubyのコードを読んでいたら見知らぬコードを発見した。

それは僕がほしくてとっさに作ったものそのものだった(それ以上だった)

http://docs.ruby-lang.org/ja/2.2.0/method/Tempfile/s/create.html

Tempfile.createはTempfile.openと似ているようでちょっと違う。

Tempfile.openではブロックの終了時(close時)ではなくGCのタイミングでファイルを削除する。

Tempfileはプログラムが異常終了してもファイルが消えた状態になるので慣例的に即unlinkして使う事が多い。 そのためpathをとったりファイルの存在確認をしたりということはあんまりないんだけど、 外部コマンドを使いたい場合はやっぱりpathがあると便利。

かといってGCタイミングでファイルを削除としていると、 例えばunicornで重い画像処理にTempfileを使っていてタイムアウトでプロセスが強制終了(kill -9)した場合、 大容量のファイルが消されずに残ってディスクフルになってましたという事故にもつながる。

そこで、

f = Tempfile.new("foo")
begin
  # ...
ensure
  f.close!
end

みたいなイディオムを書いて少しでもマシにしようとしていた。

しかしこれをバッチリメソッド化したのがTempfile.createだった。ruby 2.1.0から導入されている

Tempfile.createをブロック呼び出しすると、ブロックから出るときにファイルを削除する。

require "tempfile"

GC.disable
path = ""
Tempfile.create("foo") do |f|
  path = f.path
  p File.exist?(path) #=> true
end
p File.exist?(path) #=> false

そんな便利メソッドが、日ごろおせわになっているRubyの日本語ドキュメントるりまになかったので、 すこしでも還元できればとTempfile.createを追加するPRを送った結果できたのが冒頭のリンクというわけだ。


とはいえTempfile.createのブロックの中でkill -9されるとどうしようもできないのは変わってないのがつらいところ。 Tempfileは使い終わったらできるだけ即unlinkしよう。