diff --git a/README.md b/README.md index f0633aa..bc2c486 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ pairing with smart people at Hashrocket. For a steady stream of TILs, [sign up for my newsletter](https://tinyletter.com/jbranchaud). -_1043 TILs and counting..._ +_1044 TILs and counting..._ --- @@ -872,6 +872,7 @@ _1043 TILs and counting..._ - [Replace The Current Process With An External Command](ruby/replace-the-current-process-with-an-external-command.md) - [Require Entire Gemfile In Pry Session](ruby/require-entire-gemfile-in-pry-session.md) - [Rerun Only Failures With RSpec](ruby/rerun-only-failures-with-rspec.md) +- [Retry A Block After An Exception](ruby/retry-a-block-after-an-exception.md) - [Returning With Sequel](ruby/returning-with-sequel.md) - [rexml Is A Bundled Gem As Of Ruby 3.0.0](ruby/rexml-is-a-bundled-gem-as-of-ruby-3-0-0.md) - [Run An Older Version Of Bundler](ruby/run-an-older-version-of-bundler.md) diff --git a/ruby/retry-a-block-after-an-exception.md b/ruby/retry-a-block-after-an-exception.md new file mode 100644 index 0000000..8298a1e --- /dev/null +++ b/ruby/retry-a-block-after-an-exception.md @@ -0,0 +1,50 @@ +# Retry A Block After An Exception + +Ruby comes with a [_retry_ +mechanism](https://ruby-doc.org/docs/keywords/1.9/Object.html#method-i-retry) +that allows you to recover from known exceptions by retrying the code that led +to the exception. In network or timing-based situations where race conditions +are possible, the most straightforward recourse may be to just _retry_ a couple +times. + +Set up a `begin` / `rescue` block like you'd normally do for a chunk of code +that may raise an exception. Then add a `retry` call to the `rescue` block. + +```ruby +begin + puts "About to do a thing (#{retries})" + + raise StandardError if rand(5) != 4 + + puts "Success!" +rescue StandardError => e + retry +end +``` + +If an exception is raised, this will tell Ruby to re-execute the code in the +`begin` block over and over until the exception isn't raised. + +To avoid an infinite loop, you can limit the retries with a counting variable. + +```ruby +begin + retries ||= 0 + puts "About to do a thing (#{retries})" + + raise StandardError if rand(5) != 4 + + puts "Success!" +rescue StandardError => e + retry if (retries += 1) < 3 + + # all retries failed, re-raise exception + raise e +end +``` + +This will re-raise after 3 tries. + +Here is the [full example](https://gist.github.com/jbranchaud/629fb3b9d55c817e5c9fc480790dfabc) + +[source](https://www.honeybadger.io/blog/how-to-try-again-when-exceptions-happen-in-ruby/)