In programming, cleaning up resources you have created is an easily-overlooked problem. In languages like C, you have to clean up everything by hand: memory, files, network sockets, etc. Languages that have a garbage collector take away the need to explicitly free memory, but you still have to manage the other resources.
In Ruby, we can use blocks to help ensure resources are closed. You’ve probably seen this idiom when dealing with files. The File class ensures that the file is closed after the block is finished:
1 2 3 |
|
However, this can only be used when the lifespan of the resource is one method call. If you need to keep the file around in an instance variable, then you cannot use this pattern, and must fall back to explicitly closing the resource:
1 2 3 4 5 6 7 8 9 |
|
To make this code nicer on yourself and others that have to use it,
you should add a method that handles closing the resource for you,
just like File
does:
1 2 3 4 5 6 7 8 |
|
Unfortunately, this clean implementation of open
has a problem if
the constructor of File
can throw an exception. The exception will
occur before the variable foo
can be set to anything, so the close
message will be sent to nil
instead, causing another exception!
This certainly didn’t happen in any code I was writing…
To handle this case, we have to give up on using the implicit `begin“ block from the function and create our own scope:
1 2 3 4 5 6 7 8 9 10 |
|
Now we can safely create a Foo
and close it all in one place, but
what if another object wants to keep an instance of Foo
around for
longer? It’s nice to transparently handle both cases:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|