

Unified HTTP exception handling for Ruby - fredsters_s
https://blog.rainforestqa.com/2014-08-15-introducing-http-exceptions/

======
djur
Handy! A lot of Ruby libraries do a pretty bad job protecting their users from
underlying exceptions that should be handled within the library. I'm hoping
that with exception causes in Ruby 2.1, we'll see more libraries wrapping
common exceptions.

Another option for dealing with sloppy exception handling by libraries is
toe_tag, which we open-sourced at my work:

[https://github.com/crowdcompass/toe_tag](https://github.com/crowdcompass/toe_tag)

It allows you to declare groups of exceptions that can be caught with a single
rescue clause. This has been extremely useful when dealing with ActiveRecord's
tendency to bubble up exceptions from the underlying drivers -- the native and
JDBC drivers for Postgres raise completely different exceptions for the same
errors.

In some cases, exception classes aren't enough to determine whether an
exception actually should be caught. A lot of libraries end up forcing you to
make decisions based on the text of the message, or on some custom method
(#error_code or what have you). toe_tag helps clean up those checks too.

~~~
cheald
You can also do this without any extra gems:

    
    
        EXCEPTIONS = [Foo::Exception, Bar::Exception]
    
        begin
          # whatever
        rescue *EXCEPTIONS => e
          # Handle any exception in the array
        end
    

The checking based on exception text is great, though.

~~~
djur
This definitely works, and I've done it a lot in the past (and still would if
my requirements are simple enough), but there's a few useful things that
toe_tag does that this doesn't.

First, you can pass it an array of exception names, and it will ignore ones
that aren't defined. This is really useful if you need to group together
exceptions from multiple libraries that may or may not be loaded (this happens
a lot if you're writing an app expected to work both in MRI and JRuby).

You also don't need to know anything special about toe_tag's synthetic
exception classes to use them. No splat operator needed. You can also combine
exception groups into larger groups, which you couldn't do with nested arrays
and splat.

~~~
cheald
Oh, definitely. I didn't mean to diminish the cool things toe_tag does - I
just tend to dislike the tendency for novices to just use gems to do things
without understanding why they work, o I like to point out where solutions can
be accomplished in bare Ruby. :)

toe_tag sounds like a great tool for the toolbox, but if the need is "I want
to rescue multiple exceptions at once in a DRY fashion", there's no magic
needed.

~~~
djur
Understood and agreed, as a fellow "just use Ruby"-ist. Once you've done
something a few dozen times or so by hand, you start thinking about whether it
might be handy to have a library for it.

But as someone who is employed to maintain and improve more than one Ruby app
with more than 200 gem dependencies apiece, I can say with certitude that
there is such a thing as going too far.

I have actually found that even fairly experienced Ruby developers have a
limited understanding of how Ruby exceptions work. Usually there's one or two
gaps -- like not knowing that `rescue Exception` is a bad idea, or not knowing
`rescue => err` works (as opposed to `rescue StandardError => err`), or that
multiple rescues can be added to a single begin block (I've seen nested
`begin...rescue` constructs for exactly that reason), or that `rescue A, B`
works. Or what the return value of `begin...rescue...ensure` is.

(Or that `begin...rescue` can take an `else`, which is another example of its
shared behavior with `case...when`. I still have yet to see begin-else used in
real code, though, and I wouldn't encourage it.)

Thank you for the kind words!

------
smathieu
Original gem author here!

We were scratching out own itch by doing this. This is currently used by
several of our projects.

It does feel like the HTTP libraries should be better and handling these
various exceptions. Since they don't, we've ended up writing this.

For the most part, whenever we do any HTTP call, we are expecting a specific
return code and we want to raise an easy to handle exception when this
happens. However, many HTTP call don't even get to the point where an error
code is return when the network is not reliable. We've found that in most
case, we want to handle that exception in the same way than an unexpected
error code.

This little gem let us do that easily.

Enjoy :)

