academy

Exceptions in Ruby

Jeff Kreeftmeijer

Jeff Kreeftmeijer on

Exceptions in Ruby

An exception is a special data structure that holds information about an exceptional condition happening in your application. Exceptions are signals sent when your program can't continue running because it doesn't know how to deal with a specific situation. In Ruby, we call sending such a signal raising an exception.

1raise 'this is an exception'
2
3puts "This message won't be printed."

The quickest way to see an exception in action is to raise one yourself. By using the raise method with a message, Ruby will create a RuntimeError with the passed text as its description. It will also add a stack trace that points to where the exception was raised from in your code.

1$ ruby raise.rb
2raise.rb:1:in `<main>': this is an exception (RuntimeError)

When running the example script above, you'll notice that, as promised, the message isn't printed after the exception is raised. That's because unhandled exceptions halt execution of your program by causing a crash. This is to make sure your application doesn't keep running after failing to complete one of its tasks.

Different types of exceptions

Internally, Ruby raises exceptions when things go wrong. For example, you'll get an exception when trying to devide a number by zero.

1irb(main):001:0> 42/0
2ZeroDivisionError: divided by 0
3        from (irb):1:in `/'
4        from (irb):1
5        from /Users/jeff/.asdf/installs/ruby/2.3.0/bin/irb:11:in `<main>'

In this case, the exception's type is ZeroDivisionError, instead of the RuntimeError we saw before. There are dozens of exception types to form Ruby's exception hierarchy, and they're all raised in different situations.

RuntimeError is a more generic exception class, but there are more specific examples. A NoMethodError gets raised when trying to call a method that doesn't exist, and an ArgumentError notes that the wrong arguments are passed to an existing method, for example.

Rescueing exceptions

Most applications require the ability to recover from exceptions. In a web application, an error can happen when a user submits faulty data in a form. This should result in an error message being displayed to the user instead of crashing the whole web server.

In a case like that, an exception might get raised, but it will get rescued by the web server before reaching the top of the call stack, which prevents the exception from crashing the application.

1begin
2  raise 'this is an exception'
3rescue RuntimeError => exception
4  puts "Exception rescued: #{exception.inspect}"
5  # => "Exception rescued: #<RuntimeError: this is an exception>"
6end
7
8puts "This message *will* be printed."

By wrapping the example from before in a begin/rescue block, the exception won't get raised, and it won't crash our app. Instead, the rescue-block gets executed, which prints a message explaining the exception was thwarted, in this case. Also, because this prevents our app from crashing, the last message will get printed.

This example specifically rescues from RuntimeErrors, so any other error won't get caught. Being specific about which errors are rescued is convenient, because it'll allow you to do different things when different errors occur. Also, it's important to make sure not to rescue too many exceptions.

For a more in-depth primer on exception handling, and some tips on how to properly rescue exceptions, check out our exceptions primer on Ruby Magic.

Have any questions about raising or catching exceptions in Ruby? Please don't hesitate to let us know at @AppSignal. Of course, we’d love to know how you liked this article, or if you have another subject you’d like to know more about.

Share this article

RSS

AppSignal monitors your apps

AppSignal provides insights for Ruby, Rails, Elixir, Phoenix, Node.js, Express and many other frameworks and libraries. We are located in beautiful Amsterdam. We love stroopwafels. If you do too, let us know. We might send you some!

Discover AppSignal
AppSignal monitors your apps