Inline rescue
In Ruby, rescue can appear in multiple places:
begin/rescueblocks:
begin
# code
rescue
# code
end
def/rescue
def perform_work
# code
rescue
# code
end
- block
rescue
3.times do |attempt|
# code
rescue
# code
end
I recently learned about a fourth place rescue may be used:
- inline
rescue
risky_method rescue "a value"
Here’s an example. I have a list of URLs that I want to grab the HTML for. If there are any errors, I don’t need to know about it. I am OK with just not having that data.
require 'http'
urls = ['https://github.com', 'https://doesnotexist']
pages = urls.map { |url| HTTP.get(url) rescue nil }.compact
Now pages contains a list of HTML strings for all the pages I was able to retrieve. The rescue nil part captures any StandardError exceptions and returns nil. You can return any object you want. In this case, it was convenient to return nil so the subsequent compact could remove it from the final array.
The above code is equivalent to:
pages = urls.map do |url|
HTTP.get(url)
rescue
nil
end.compact
One of the caveats of using inline-rescue is that it swallows a very general exception, and there may be some exceptions, either now or with future code changes, which you might want to handle or allow to propagate instead of returning the value.