3

Is there a way to catch any type of error the Ruby/Rails encounters?

I am making a network request. What I have seen so far is, it can return 404, timeout or even any empty response object?

I have handled them individually, it is not DRY, but is there a way to handle all these and those which I have not seen yet gracefully?

Many times even when the response object is analysed, sometimes it may not contain what I am looking for. Sure I can handle them individually.
I am curious to know if it is possible to define a use case to work with, everything apart from it, which I have not imagined, is just thrown an exception and does not break my application.

Is generic error handling possible in Ruby?

arjun
  • 1,594
  • 16
  • 33
  • Would you not be better off using something like [Better Errors](https://github.com/charliesome/better_errors)? – SRack Mar 19 '18 at 16:15
  • @SRack, I also use Better Errors, but I believe OP is looking to handle requests from outside of the network? – Daryll Santos Mar 19 '18 at 16:35
  • Cheers Daryll, makes sense. Also, going to leave this here as very worthwhile reading: https://stackoverflow.com/questions/10048173/why-is-it-bad-style-to-rescue-exception-e-in-ruby/10048406#10048406 – SRack Mar 19 '18 at 16:56
  • @SRack There is a caveat there in BetterErrors, it discourages using it in production. I really dont want to be bothered about that. But I didn't know about BetterErrors. So thanks. – arjun Mar 20 '18 at 04:38

2 Answers2

3

Yes its absolutely possible, there are a couple of different levels of rescuing exceptions in Ruby, as noted by Daryll you can specify different exceptions that go to the same handler like

begin
  # potentially exception raising code
rescue Exception1, Exception2 => e
  # run code if Exception1 or Exception2 get raised
end

You can also catch StandardError, which most Exceptions that you would want to catch inherit from. This is a good option if your looking for a catch all, like try this and keep going no matter what.

begin
  # potentially exception raising code
rescue StandardError => e
  # run code if StandardError or anything that inherits from StandardError is raised (most errors)
end

You can also catch Exception (Dangerous), which every Exception inherits from (including StandardError). You pretty much never want to do this since things like SyntaxErrors, SignalExceptions (you can catch Control-C and prevent terminating your script with it) and other internal errors also inherit from Exception. See http://blog.honeybadger.io/ruby-exception-vs-standarderror-whats-the-difference/ for some more details

begin
  syntax exception
rescue => e
  puts "I even catch syntax errors!!!"
end
puts "I'll keep on executing though"
  • I have tried these but they don't catch Gem specific errors. Have to define for each of those classes. – arjun Mar 20 '18 at 04:48
  • Ahh. Sorry. Had a typo. So the best thing is to raise `StandradError`. This should give some piece of mind, right? – arjun Mar 20 '18 at 04:57
  • yeah I'd say rescuing `StandardError` is probably what your looking for. If it were me, I'd still handle exceptions vs empty / bad responses separately, since you wouldn't have a response to go through if there was an error. Although if I had the same logic regardless if there was an error or an empty response, I'd just throw that into a method and call them in both the rescue and when you don't find what your looking for in the response – baseballlover723 Mar 20 '18 at 20:21
2

Are you looking for something like this? Source.

begin
  rand(2) == 0 ? ([] + '') : (foo)
rescue TypeError, NameError => e
  puts "oops: #{e.message}"
end

If you are looking to implement these things in controllers, and want to DRY it up, try out rescuable. Ruby API link.

class ApplicationController < ActionController::Base
  rescue_from User::NotAuthorized, with: :deny_access # self defined exception
  rescue_from ActiveRecord::RecordInvalid, with: :show_errors

  rescue_from 'MyAppError::Base' do |exception|
    render xml: exception, status: 500
  end

  private
    def deny_access
      ...
    end

    def show_errors(exception)
      exception.record.new_record? ? ...
    end
end
Daryll Santos
  • 2,031
  • 3
  • 22
  • 40
  • Nice. Worth adding `StandardError` to those rescued to be comprehensive? – SRack Mar 19 '18 at 16:55
  • Based on [this article](http://blog.honeybadger.io/understanding-the-ruby-exception-hierarchy/), it's the default one :) – Daryll Santos Mar 19 '18 at 16:57
  • 1
    Ah, very handy. Cheers @DaryllSantos. +1 – SRack Mar 19 '18 at 16:58
  • In the SO you have linked, one of the comments suggests that it is better to rescue from the Gem specific classes. Isn't that unmaintainable? – arjun Mar 20 '18 at 04:35
  • Also, does standalone Ruby have a DRY way to do these? – arjun Mar 20 '18 at 04:58
  • For gem specific errors--what you can do is to localize the parts of your app that interact with that gem, and rescuing and re-raising them to your own error classes. Read a bunch of articles on the Adapter pattern for 3rd party APIs (or code you don't own). [This was the first that showed up on Google for me.](http://www.thegreatcodeadventure.com/rails-refactoring-part-i-the-adapter-pattern/) – Daryll Santos Mar 20 '18 at 10:05