Few languages have any procedural way to do that.
If Ruby had some way to state "the opposite of opening a file is closing a file" and then use it everywhere, we could do that. The block-syntax open is nearly that, but not quite. You'd need to have no non-block-scope way to use the resource for it to work.
RAII would also give the same benefit, if there were no non-RAII way to declare the resource.
This very significant property is what makes me love RAII. I don't count C#'s using-statement and/or rubys block statement as RAII since it relies on useage patterns. C++'s automatic destruction of graphs of objects also makes it outshine all other methodologies, and the guaranteed destruction is the key here.
Once you're passing a block to a method like this in Ruby, the execution of the cleanup code is just as guaranteed as it is in C++.
You do however have a point when you say that you can miss deallocation and that is just as easy as forgetting to put a variable in a block. In an ideal world I would like to be able to decouple de-allocation time from destruction time, as someone mentioned above they are completely orthagonal issues. If this would be possible, one could guarantee the destructor callback, but defer deallocation until later. This would probably give leeway to more effective memory allocation patterns while keeping RAII alive.
And another thing about blocks: how do you deal with trees and graphs of objects? That is not trivial when using blocks. You can get around it, but continuing that way would most likely lead you to something like Haskells monads (the "programmable semicolon" aspect of them).
You can already do that, just `return unless block_given?`. In principle I don't see why you'd want to non block version anyway but maybe there's some use case where that is valid.
C#'s IDIsposable has this, too.
So do other languages. It's really not that unusual a pattern.