Error Handling Rails
Contents |
Web Dev @ Microsoft SEO By WooRank Books Courses Screencasts Newsletters Versioning Shop Forums Advertise Contribute Contact Us Our Story 995kSubscribers 132kFollowers 80kFollowers Ruby rails exception message Article Ruby Error Handling, Beyond the Basics By Darko Gjorgjievski June 16, 2015
Rails Error Handling Best Practices
Imagine you're riding a bike. Now, imagine the designers of that bike built it so it rides smoothly only on
Rails Controller Error Handling
roads without bumps and encountering one would result in the entire bicycle breaking! You wouldn't want that, would you? Yet this is how thousands of software developers design their software every single day. They
Rails Throw Error
put error handling in as an afterthought, dealing with it only when it's inevitable. The truth is, it's not their fault. Most of the material on this subject is very basic, covering simple things like raising an error, rescuing it, different error types and…that's about it. This article will attempt to go deeper than that. I assume you're familiar with the basics of error handling (using raise, begin/rescue, rails raise error with message what StandardError is, error inheritance). That's the only prerequisite for reading this article. Let's begin. What Did We Do Before Raising/Handling Exceptions? Before exceptions were invented, the primary method of communication that something in the program has failed was through error return codes. As time passed, people looked at ways to clearly distinguish between what their program does and what would happen if it didn't do what it was supposed to (return codes were far from ideal for this purpose) do. Thus, the invention of language constructs like: raise rescue begin/end (Many other languages use different wording, like try/catch or throw, but the idea behind it remains the same.) There are opposing views to using exceptions and error handling in the first place. Some of these points make sense and we'll discuss them later in the article. For now, let's get you familiar with some of the ways of handling errors in Ruby that can help you manage them better. Cleanup Before Crashing Often we have no idea when our program is going to crash. What if we needed to do some cleanup operations before our program ends (due to an error)? That's where at_exit comes to the rescue: puts 'Hell
here for a quick overview of the site Help Center Detailed answers to any questions you might have Meta Discuss the workings and policies of this site About Us Learn more about Stack Overflow the company Business Learn rails catch all exceptions more about hiring developers or posting ads with us Stack Overflow Questions Jobs Documentation Tags Users rails 3 error handling Badges Ask Question x Dismiss Join the Stack Overflow Community Stack Overflow is a community of 4.7 million programmers, just like you, helping ruby error handling each other. Join them; it only takes a minute: Sign up Ruby on Rails Error Handling, Catching Error and Message up vote 0 down vote favorite I'm trying to figure out the best way to catch a specific https://www.sitepoint.com/ruby-error-handling-beyond-basics/ error thrown AND the error's message in Ruby on Rails. My use case is that I encounter a timeout error every now and then which is thrown with a general error and I want to treat the timeout error differently than other errors within the same general error. I'm not sure what other type of errors could be thrown in the general error but I assume more of them exist. I have some sample code below http://stackoverflow.com/questions/34496989/ruby-on-rails-error-handling-catching-error-and-message of how I'm currently handling it, but I was thinking there might be a better way which I haven't found yet? tries = 0 begin tries += 1 rescue Foo::Bar => e case e.to_s when 'More specific timeout error message' retry unless tries >= 5 else # Let me see other error messages log.info("Error: #{e.to_s}") end end ruby-on-rails ruby error-handling rescue share|improve this question asked Dec 28 '15 at 16:22 CarlyL 715 Are you sure that timeout is being raised using a general purpose exception class instead of its own class, like Timeout::Error? –Alexandre Angelim Dec 28 '15 at 17:56 Yeah, so the error is coming from an external library which times out from time to time and returns the external libraries general error with the timeout message. –CarlyL Dec 28 '15 at 18:00 add a comment| 2 Answers 2 active oldest votes up vote 0 down vote Take a look at retriable gem. It seems like a good fit for what you're proposing. Usually you'd rescue from an specific error type, but retriable also gives you the choice to rescue based on the error message. begin Retriable.retriable on: { Foo::Bar => /More specific timeout error message/ }, tries: 3 do # will retry if an error of type Foo::Bar is raised # and its message matches /More specific timeout error message/
those solutions. Let me walk you through the possibilities. begin/rescue block begin/rescue blocks are the standard ruby mechanism to deal with exceptions. It might look like this: begin do_something rescue handle_exception end https://blog.simplificator.com/2015/03/13/handling-errors-in-ruby-on-rails/ This works nice for exceptions that might happen in your code. But what if you want to rescue every occurrence of a specific exception, say a NoPermissionError which might be raised from your security https://reinteractive.net/posts/269-exceptional-error-handling-in-ruby layer? Clearly you do not want to add a begin/rescue block in all your actions just to render an error message, right? Around filter An around filter could be used to catch all those error handling exceptions of a given class. Honestly I haven't used a before filter for this, this idea came to my mind when writing this blog post. class ApplicationController < ActionController::Base around_action :handle_exceptions private def handle_exceptions begin yield rescue NoPermissionError redirect_to 'permission_error' end end end rescue_from rescue_from gives you the same possibilities as the around filter. It's just shorter and easier to read and if the error handling rails framework offers a convenient way, then why not use it. There are multiple ways to define a handler for an exception, for a short and sweet handler I prefer the block syntax: class ApplicationController < ActionController::Base rescue_from 'NoPermissionError' do |exception| redirect_to 'permission_error' end end exceptions_app There is an additional feature (added in Rails 3.2) that allows to handle exceptions. You can specify an exceptions_app which is used to handle errors. You can use your own Rails app for this: config.exceptions_app = self.routes If you do so, then your routing must be configured to match error codes like so: match '/404', to: 'exceptions#handle_404' ... Alternatively you can specify a lambda which receives the whole Rack env: config.exceptions_app = lambda do |env| # do something end Do you wonder how you can call an arbitrary action when you have the env? It's pretty easy: action = ExceptionsController.action(:render_error) action.call(env) In any case you want to set following configuration for exceptions_app to be used: Rails.application.config.consider_all_requests_local = false Rails.application.config.action_dispatch.show_exceptions = true But where is the exception you ask? It is stored in the Rack env: env['action_dispatch.exception'] And as a bonus: here is how you can determine an appropriate status code for an exception: wrapper = ActionDispa
handling in Ruby By Yuji Yokoo, 18 December 2015 twitter Scroll down to read I recently come across some surprising code involving exceptions which prompted me to look a bit deeper into exceptions in Ruby. In this post, I would like to share some of what I found. Exception vs StandardError This is where it all started. I had a script that did something like the following (it was not quite this simple, but it shows the important parts): class MyLib class MyLibBaseError < Exception ; end class MyIOError < MyLibBaseError ; end def do_something raise MyIOError rescue puts "logging error: #{$!.message}" # $! is the last exception raised end end Calling do_something results in this: > MyLib.new.do_something MyLib::MyIOError: MyLib::MyIOError from (irb):70:in `do_something' from (irb):76 from /Users/yuji/.rvm/rubies/ruby-2.1.7/bin/irb:11:in `<