RAII in Ruby (Or, How to Manage Resources in Ruby)
destructor, finalizer, raii, resources, ruby
Solution
So that users don't "have to remember to do the whole begin-rescue-ensure chacha" combine `rescue`/`ensure` with `yield`.
class SomeResource
...
def SomeResource.use(*resource_args)
# create resource
resource = SomeResource.new(*resource_args) # pass args direct to constructor
# export it
yield resource
rescue
# known error processing
...
ensure
# close up when done even if unhandled exception thrown from block
resource.close
end
...
end
Client code can use it as follows:
SomeResource.use(connection_string) do | resource |
resource.do_something
... # whatever else
end
# after this point resource has been .close()d
In fact this is how `File.open` operates - making the first answer confusing at best (well it was to my work colleagues).
File.open("testfile") do |f|
# .. process - may include throwing exceptions
end
# f is guaranteed closed after this point even if exceptions are
# thrown during processing
Problem
I know it's by design that you can't control what happens when an object is destroyed. I am also aware of defining some class method as a finalizer. However is the ruby idiom for C++'s RAII (Resources are initialized in constructor, closed in destructor)? How do people manage resources used inside objects even when errors or exceptions happen? Using ensure works: ``` f = File.open("testfile") begin # .. process rescue # .. handle error ensure f.close unless f.nil? end ``` but users of the class have to remember to do the whole begin-rescue-ensure chacha everytime the open method needs to be called. So for example, I'll have the following class: ``` class SomeResource def initialize(connection_string) @resource_handle = ...some mojo here... end def do_something() begin @resource_handle.do_that() ... rescue ... ensure end def close @resource_handle.close end end ``` The resource_handle won't be closed if the exception is cause by some other class and the script exits. Or is the problem more of I'm still doing this too C++-like?