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
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 returns
'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
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('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
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.
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.
The Ruby logo is Copyright © 2006, Yukihiro Matsumoto, distributed under CC BY-SA 2.5.