David Suarez de Lis <excalibor / demasiado.com> writes: > Hi all, > > from the User's Manual: > http://www.math.sci.hokudai.ac.jp/~gotoken/ruby/ruby-uguide/uguide25.html > > ruby> begin > ruby| file = open("/tmp/some_file", "w") > ruby| # something to do > ruby| ensure > ruby| file.close > ruby| end > > Let's suppose /tmp/some_file does not exist: then I get, from the ensure part: > > NameError: undefined method `close' for nil > > Obviously, as open has failed in opening the file, 'file' references 'nil'... > > How do we cope with this kind of things? The issue really is that there are two levels of exception here, but there's only one exception handler. Let's look at it a different way. We'll start by opening the file. file = open(...) hmmm, we think, that might raise an exception which we'll want to handle, so let's wrap it: begin file = open(..) file.close rescue ... do whatever end Note how we can just use 'file.close', as we can assume the file object is OK. Now we need to process the contents: begin file = open(..) process.. process.. file.close rescue ... do whatever end hmmm, we say again, the processing might itself raise an exception, which would bypass the file.close, so we need another wrapper: begin file = open(..) begin process.. process.. ensure file.close end rescue ... do whatever end et voila! However, you'd probably write this more simply using the block form of File.open: File.open(...) do |file| process... end This does the necessary handling to ensure that the file is closed at the end of the block's execution. Regards Dave