Ruby’s New Exception Keyword Arguments

Ruby’s New Exception Keyword Arguments

exception: false and exception: true

In Ruby 2.6, a variety of Kernel methods get a new exception: false or exception: true keyword argument. When Kernel methods fail, some raise an error and some just return nil. This new feature lets you override that default behavior.

TL;DR: In Ruby 2.6 these examples will all work:

system 'not-a-command', exception: true
#!> Errno::ENOENT: No such file or directory - not-a-command

Integer('not-a-number', exception: false)
#=> nil

Float('not-a-number', exception: false)
#=> nil

Complex('not-a-number', exception: false)
#=> nil

Rational('not-a-number', exception: false)
#=> nil

Background

What should Ruby do when unexpected things occur? Fail loudly? Carry on silently? It depends. There are reasons you may prefer to handle errors differently.

Many methods have a default behavior to either return nil or raise an error when something goes wrong. Ruby chooses what’s most appropriate as a default on a method-by-method basis.

One example of Ruby having various default behaviors is string-to-number conversion. For example,'nope'.to_i is permissive and returns0, since 'nope' isn’t a number. On the other hand, Integer('nope') is strict, and raises an error. Here are a few examples of how this works:

'42'.to_i
#=> 42
'42x'.to_i
#=> 42
'Square'.to_i
#=> 0

Integer('42')
#=> 42
Integer('42x')
#!> ArgumentError: invalid value for Integer(): "42x"
Integer('Square')
#!> ArgumentError: invalid value for Integer(): "Square"

The permissive String#to_i method is lax about detecting a number. When one can’t be found it just provides a default value of zero. Alternately, the strict Kernel#Integer method raises an error. If you want strict parsing but no error in Ruby 2.5 and earlier, it’s up to you to manually rescue:

Integer('nope') rescue nil
#=> nil

Exception False with Numeric Conversion

The problem with rescuing manually is that it’s slow and noisy. On my machine, it’s almost three times faster to use exception: false:

In Ruby 2.6, you’ll be able to use Integer('nope', exception: false) instead of Integer('nope') rescue nil for much better performance. The same applies to Float, Rational and Complex.

Float('nope', exception: false) instead of Float('nope') rescue nil

Exception True with System

The new exception keyword arguments are also available for Kernel#system. If command execution fails, the #system method’s default behavior is to fail silently and return nil:

system 'nope'
#=> nil

Before, you had to write the message and raise the error yourself if you wanted to have #system raise an error on execution failure. Now you can simply add exception: true and you’ll get an error raised with a nicely formatted message:

system 'nope', exception: true
#!> Errno::ENOENT: No such file or directory - nope

When command execution succeeds but there’s a non-zero exit status, exception: true will also cause an error to be raised instead of the false return value.

Conclusion

Thanks to Aaron Patterson for proposing this feature for numeric conversion. And thanks to Takashi Kokubun for proposing this feature for #system. The new exception: keyword arguments will ship with Ruby 2.6 when it’s released on Dec 25, 2018. These changes didn’t make it into ruby-2.6.0-preview1 but they will be part of the upcoming ruby-2.6.0-preview2 release and are available now on the nightly snapshots.

We use Ruby for lots of things here at Square — including our Square Connect Ruby SDKs and open source Ruby projects. We’re eagerly awaiting the release of Ruby 2.6!

The Ruby logo is Copyright © 2006, Yukihiro Matsumoto, distributed under CC BY-SA 2.5.The Ruby logo is Copyright © 2006, Yukihiro Matsumoto, distributed under CC BY-SA 2.5.

Want more? Sign up for your monthly developer newsletter or drop by the Square dev Slack channel and say “hi!”

Table Of Contents
View More Articles ›