13
\$\begingroup\$

What would be a prettier/faster way to do handling of multiple errors in Ruby? Here is the code I am working with:

begin
  response = session.get url
rescue Patron::HostResolutionError
  puts "Error resolving remote host."
  exit 1
rescue Patron::PartialFileError
  puts "File size mismatch. (Host reported a file size, but the actual file is of different size)"
  exit 1
rescue Patron::TimeoutError
  puts "Operation timed out."
  exit 1
rescue Patron::TooManyRedirects
  puts "Tried redirecting too many times."
  exit 1
rescue Patron::URLFormatError
  puts "Error with the URL format"
  exit 1
rescue Patron::UnsupportedProtocol
  puts "This URL is using a protocol that we cannot handle."
  exit 1
rescue Patron::ConnectionFailed
  puts "Error connecting to host. Check your internet connection."
  exit 1
end
\$\endgroup\$
15
\$\begingroup\$

Since you're rescuing all 7 subclasses of Patron::Error, it would make sense to directly rescue Patron::Error rather than rescuing them one by one.

You're also duplicating work that has already been done for you, by formulating your own error message for each exception: the exceptions will already contain a useful error message, which even contains more information than yours do (for example if the host could not be resolved, the exception's message will contain the hostname that could not be resolved instead of just saying "Error resolving remote host").

Lastly I would print error messages to stderr, not stdout, as that's where they're supposed to go.

So I would write the code like this:

begin
  response = session.get url
rescue Patron::Error => e
  $stderr.puts e.message
  exit 1
end
\$\endgroup\$
1
\$\begingroup\$

Your begin/rescue code does look repetitive, but on the hand it would be easy to extend in the future. If you are certain you will always have this structure (rescue with an error message + exit), you can abstract it, for example:

exceptions = {
  Patron::HostResolutionError => "Error resolving remote host.",
  ...
}

response = catch_exceptions(exceptions, :exit_code => 1) { session.get(url) }

It's usually handy to write this kind of wrappers so the main code keeps clean (on the other hand, if it gets messier and convoluted it's a good sign the abstraction is just not working).

\$\endgroup\$
  • \$\begingroup\$ Apparently, catch can only take 0..1 arguments. As I get an error saying so when I try to run this. \$\endgroup\$ – Mark Szymanski Apr 23 '11 at 23:03
  • \$\begingroup\$ @Mark. Sorry, I didn't mean Ruby's catch, this is a custom method. Call it with a different name: catch_exceptions, for example. \$\endgroup\$ – tokland Apr 24 '11 at 6:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.