Brian
Brian

Reputation: 7135

How to know what exceptions to rescue?

I often find myself without knowing what exceptions to rescue when using a specific library of code in Ruby.

For instance, I often use HTTParty for any HTTP requests my rails/sinatra app would make. I dug around the code for HTTParty and found a file containing the defined exceptions used. Great! I'll just rescue them when making a request.

To test it out, I put in a bogus domain name for the request, but instead of HTTParty::ResponseError exception I expected, I instead get got a SocketError exception.

What is the best way to deal with this? I'm aware that HTTParty is a wrapper for Ruby's implementation, and that's probably what threw the SocketError exception. But how would I know that normally?

I could solve this by just rescuing "Exception", but that's pretty awful practice. I'd rather be well aware of the exceptions I could be causing and dealing with those.

EDIT: I should clarify that what really prompted me to create this question was that I have no idea how I can figure out the possible exceptions that CAN be raised when calling a specific function... that is, without looking through every single function call in the stack.

Upvotes: 5

Views: 605

Answers (3)

Aaron Thomas
Aaron Thomas

Reputation: 5281

For libraries or gems where the source code is publicly available, you can typically find the types of exceptions in an exceptions.rb file. (Ref here). Otherwise you will have to rely on the documentation. If all else fails you can rescue StandardError, although it is a less-than-ideal practice in many cases (ref this SO answer.

Upvotes: 0

Russ Clarke
Russ Clarke

Reputation: 17909

A socketError response is totally fine if you put in a bogus domain name. After all - trying to connect to a non-existant domain would cause the connection to fail AKA SocketError.

The best way to deal with that is to use a valid Domain with a false URL in your test, but catch socketError in your live code.

The problem here is not that you're catching the wrong exception but that you're priming the test with bad data.

The best course of action is understand what exceptions could happen and manage them, When I say understand, I'm getting at - Where does the URL come from, is it entered by your user ? if so never trust it and catch everything. Does it come from your config data; Semi trust it and log errors, unless it's mission critical that the URL is ok.

There's no right or wrong answer here but this approach will, I hope, give you a good result.

Edit: What I'm attempting to do here is advocate the mindset of a programmer that is aware of the results of their actions. We all know that trying to connect to 'thisServiceIsTotallyBogus.somethingbad.notAvalidDomain' will fail; but the mindset of a programmer should be to first validate exactly where that domain comes from. If it is inputted by the user then you must assume full checks; if you know it's from a config file only accessed by yourself or your support team; you can relax a little; Sadly though, this is a bad example as you should really always test URLS because sometimes the internet doesn't work!

Ideally, the developer documentation for anything you use should tell you what exceptions that it can throw.

Upvotes: 0

Preet Sangha
Preet Sangha

Reputation: 65496

In general terms (I'm not a ruby programmer) I use the following approach.

I deal with exceptions in the following way:

  • Can I recover from it? If the exception can happen and I know I can recover or retry perhaps, then I handle the exception.

  • Does it need to be reported? If the exception can happen but I know I can't recover or retry perhaps, then I handle the exception by logging it and then passing it on to the caller. I always do this on natural subsystem boundary like major module or services. Sometimes (dependant on the API) I might wrap the exception with a 'my module' specific one so that the caller only has deal with my exceptions.

  • Can't handle it? All exceptions that are not dealt with should be caught at the top level and (a) reported, (b) ensure that the system remains stable and consistent. This is the one that should always be there regardless of whether the other two are done.

Of course there is another class of exception - the ones that are so serious that they give you no chance to deal with them. For these there is only one solution -Post Mortem debugging and I find the best thing for this is logs, logs and more logs. And having worked on many system from small to large, I would prefer to sacrifice performance for stability and recoverability (except where it's critical) and add copious amounts of logging - introspectively if possible.

Upvotes: 7

Related Questions