ruby
208 lines · 3 tabs
Sarah Mitchell
Feb 2026
3 tabs
# Basic exception handling
begin
result = 10 / 0
rescue ZeroDivisionError => e
puts "Error: #{e.message}"
result = nil
end
# Multiple rescue clauses
begin
# Risky operation
file = File.open('nonexistent.txt')
rescue Errno::ENOENT => e
puts "File not found: #{e.message}"
rescue IOError => e
puts "IO Error: #{e.message}"
rescue StandardError => e
puts "Standard error: #{e.message}"
ensure
# Always runs, even if exception occurs
file&.close
end
# Rescue and retry
attempts = 0
begin
attempts += 1
# Network call that might fail
response = HTTParty.get('https://api.example.com/data')
rescue Net::OpenTimeout, Net::ReadTimeout => e
if attempts < 3
sleep(2 ** attempts) # Exponential backoff
retry
else
raise # Re-raise after max attempts
end
end
# Inline rescue
value = risky_method rescue default_value
user = User.find(params[:id]) rescue nil
# Rescue in methods (implicit begin)
def fetch_user(id)
User.find(id)
rescue ActiveRecord::RecordNotFound
User.new(name: 'Guest')
end
# Raising exceptions
raise "Something went wrong"
raise ArgumentError, "Invalid argument"
raise ArgumentError.new("Invalid argument")
# Re-raising with modification
begin
# Operation
rescue StandardError => e
raise StandardError, "Failed: #{e.message}", e.backtrace
end
# Custom exception classes
class ApplicationError < StandardError; end
class AuthenticationError < ApplicationError; end
class AuthorizationError < ApplicationError; end
class ValidationError < ApplicationError
attr_reader :errors
def initialize(errors)
@errors = errors
super("Validation failed: #{errors.join(', ')}")
end
end
# Usage
def authenticate_user(credentials)
raise AuthenticationError, "Invalid credentials" unless valid?(credentials)
# Authentication logic
end
def authorize_user(user, action)
raise AuthorizationError, "Not authorized to #{action}" unless user.can?(action)
# Authorization logic
end
def validate_input(data)
errors = []
errors << "Name is required" if data[:name].blank?
errors << "Email is invalid" unless data[:email]&.match?(/@/)
raise ValidationError.new(errors) if errors.any?
end
# Catching custom exceptions
begin
validate_input(params)
rescue ValidationError => e
render json: { errors: e.errors }, status: :unprocessable_entity
rescue AuthenticationError => e
render json: { error: e.message }, status: :unauthorized
rescue AuthorizationError => e
render json: { error: e.message }, status: :forbidden
end
# Exception with custom data
class APIError < StandardError
attr_reader :status_code, :response_body
def initialize(message, status_code:, response_body: nil)
@status_code = status_code
@response_body = response_body
super(message)
end
end
# Usage
raise APIError.new(
"API request failed",
status_code: 500,
response_body: { error: "Internal error" }
)
# Exception translation pattern
class ExternalAPIClient
class APIError < StandardError; end
class NotFoundError < APIError; end
class RateLimitError < APIError; end
def fetch_data(id)
response = HTTParty.get("https://api.example.com/items/#{id}")
case response.code
when 200
response.parsed_response
when 404
raise NotFoundError, "Item #{id} not found"
when 429
raise RateLimitError, "Rate limit exceeded"
else
raise APIError, "Request failed with status #{response.code}"
end
rescue HTTParty::Error => e
raise APIError, "HTTP error: #{e.message}"
end
end
# Circuit breaker pattern
class CircuitBreaker
class CircuitOpenError < StandardError; end
def initialize(threshold: 5, timeout: 60)
@failure_count = 0
@threshold = threshold
@timeout = timeout
@last_failure_time = nil
@state = :closed
end
def call
raise CircuitOpenError if open?
yield
on_success
rescue StandardError => e
on_failure
raise
end
private
def open?
@state == :open && Time.now - @last_failure_time < @timeout
end
def on_success
@failure_count = 0
@state = :closed
end
def on_failure
@failure_count += 1
@last_failure_time = Time.now
@state = :open if @failure_count >= @threshold
end
end
# Safe navigation with exceptions
def safe_find(model, id)
model.find(id)
rescue ActiveRecord::RecordNotFound
nil
end
# Exception logging
begin
dangerous_operation
rescue StandardError => e
Rails.logger.error("Operation failed: #{e.class.name} - #{e.message}")
Rails.logger.error(e.backtrace.join("\n"))
# Report to error tracking service
Sentry.capture_exception(e)
raise
end
# Suppressing exceptions (use sparingly!)
suppress(Errno::ENOENT) do
File.delete('tmp/cache.dat')
end
3 files · ruby
Explain with highlit
Ruby's exception handling uses begin/rescue/ensure/end. I rescue specific exceptions before general ones. rescue catches exceptions; ensure runs cleanup code always. retry attempts operation again; raise re-raises exceptions. Custom exceptions inherit from StandardError. Multiple rescue clauses handle different error types. Exception messages and backtraces aid debugging. I use inline rescue for simple cases—value = risky_method rescue default_value. Rescue modifiers catch and suppress errors—useful but potentially dangerous. Exception handling enables graceful degradation. Proper error management improves robustness and user experience. Understanding Ruby's exception hierarchy guides rescue strategies.
Related snips
ruby
class Money
include Comparable
attr_reader :amount, :currency
def initialize(amount, currency = 'USD')
Value objects for domain modeling
ruby
value-objects
domain-driven-design
by Sarah Mitchell
2 tabs
javascript
// Creating a Promise
const myPromise = new Promise((resolve, reject) => {
const success = true;
setTimeout(() => {
if (success) {
Promises and async/await patterns for asynchronous JavaScript
javascript
promises
async-await
by Alex Chang
1 tab
ruby
# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
default from: 'noreply@example.com'
def welcome_email(user)
@user = user
ActionMailer advanced patterns for transactional emails
ruby
rails
action-mailer
by Sarah Mitchell
2 tabs
ruby
# BAD: N+1 query problem
@users = User.all
@users.each do |user|
puts user.posts.count # Fires query for each user!
end
ActiveRecord query optimization and N+1 prevention
ruby
rails
activerecord
by Sarah Mitchell
3 tabs
ruby
# Installation
# rails active_storage:install
# rails db:migrate
# config/storage.yml
local:
ActiveStorage for file uploads and attachments
ruby
rails
active-storage
by Sarah Mitchell
2 tabs
ruby
class CreateDeadJobs < ActiveRecord::Migration[7.1]
def change
create_table :dead_jobs do |t|
t.string :jid, null: false
t.string :queue, null: false
t.string :klass, null: false
Background Job Dead Letter Queue (DLQ) Table
rails
reliability
background-jobs
by codesnips
4 tabs
Share this code
Here's the card — post it anywhere.