Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the clearest way to open a file and do "rescue" when it cannot be opened in Ruby

Tags:

ruby

rescue

I am now dealing with this issue by using the following code

begin
  File.open(filename, 'r')
rescue
  print "failed to open #{filename}\n"
  exit
end

Is there any way to do it more easily like Perl 'open (IN, $filename) || die "failed to open $filename\n"' Thanks.

like image 210
user3477465 Avatar asked Apr 06 '14 18:04

user3477465


2 Answers

File.open("doesnotexist.txt", 'r')

Is enough. If the file does not exist, this will raise an Exception. This is not caught, so the program exits.

# =>test6.rb:1:in `initialize': No such file or directory @ rb_sysopen - doesnotexist.txt (Errno::ENOENT)
like image 153
steenslag Avatar answered Sep 22 '22 04:09

steenslag


I'm not sure what you're trying to accomplish other than trying to write Perl with Ruby. You have to consider the fact that Perl's open returns "nonzero on success, the undefined value otherwise. If the open involved a pipe, the return value happens to be the pid of the subprocess."

Ruby's File::open however raises an exception Errno::ENOENT which is completely different behavior than returning some Ruby equivalent to undefined (I guess nil).

Write Ruby if your tool is Ruby. Write Perl if your tool is Perl. Don't write Perl if your tool is Ruby. Don't write Ruby if your tool is Perl.

UPDATE:

As @steenslag answered, simply not rescueing the exception is sort of an equivalent since the exception will act as an implicit die equivalent of Perl.

File.open filename

However you are now restricted to outputting the exception's message value as the output. For example:

in `initialize': No such file or directory @ rb_sysopen - filename (Errno::ENOENT)

If you need to output your own message you'll have to catch the exception and handle it. This is the behavior of File.open so you'll have to use it as intended. I would also argue you should explicitly specify the exception type to catch, as well as write to $stderr:

begin
  File.open filename do |f|
    puts f.gets
    # ...
  end
rescue Errno::ENOENT => e
  $stderr.puts "Caught the exception: #{e}"
  exit -1
end

Which would output the message specified to standard error and exit the program with an non-zero status (which is the behavior of die):

Caught the exception: No such file or directory @ rb_sysopen - filename

For the record I absolutely love Perl. Ruby actually shares a lot of similar characteristics of Perl (among other languages and paradigms). But when I'm writing Perl I use Perl idioms, and when I write Ruby I use Ruby idioms. The reason I'm stressing "don't write Perl with Ruby" so much is because languages have their idioms for a reason and you can end up making your colleagues mad if you don't do things "the Ruby way" or "the Perl way" with each respective language.

like image 26
James Avatar answered Sep 24 '22 04:09

James