I ran into a situation recently where I was writing a library that utilized large files. Specifically a GTFS feed parser. I wanted to cache the files away someplace so I could safely access them for the life of an object, but I didn’t want to leave them hanging around afterwards. I couldn’t do all my work inside a block passed to Dir.mktmpdir because I was planning on accessing the cache when necessary (not just one big up front parsing operation).
This got me wondering: “does Ruby have finalizers?”. It turns out it does in the form of ObjectSpace#define_finalizer. It’s worth mentioning that there are some tricks to using them which are nicely documented on Mike Perham’s blog here.
The gist of it is this: don’t create finalizers which hold a reference to the instance they’re finalizing or it just won’t work. I’m glad I found that blog post before I started coding because I would have certainly fallen into the trap he describes. It probably doesn’t help that the ruby doc examples don’t include any examples of adding a finalizer in a class definition.
So all of this works out pretty nicely and leaves me with code looking something like this: