Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save arthurariza/c31fae7221cafd4c068e333cc9e572a6 to your computer and use it in GitHub Desktop.
Save arthurariza/c31fae7221cafd4c068e333cc9e572a6 to your computer and use it in GitHub Desktop.
Exceptional Ruby: Master the Art of Handling Failure in Ruby by Avdi Grimm
# Great book! Here are my quiz notes:
# What is the diff bt raise and fail?
#=> no diff
# Are raise//fail ruby keywords or methods?
#=> Kernel#raise (are methods)
# Global exception variable
# => $! or $ERROR_INFO.inspect
require ’English’
begin
puts $!.inspect
raise "Oops"
rescue
puts $!.inspect
puts $ERROR_INFO.inspect
end
puts $!.inspect
# Re-raise last exception
# With no arguments will re-raise exception in $! If nil then RuntimeError
# note $! value is nil initialized as soon as the begin..rescue.end block terminates raise
# What is the third argument of raise and give an example of what to put there.
#=> the backtrace, use for example Kernel#caller
# What is catch/throw used for?
#=> not related to exceptions, catch/throw allows you to quickly exit blocks back to a point where a catch is defined for a specific symbol
# Retry
tries = 0
begin
tries += 1
puts "Trying #{tries}..."
raise "Didn’t work"
rescue
retry if tries < 3
puts "I give up"
end
# Diffs bt `redo` vs `retry`
#=> Both ruby keywords are used to re-execute parts of a loop but:
# redo only repeats the current iteration
# retry repeats the whole loop from the start in 1.8 but in 1.9 gives SyntaxError: Invalid retry
# Note retry should only be used inside immediate rescue blocks
# - What's caller() method used for, where's defined and what param takes?
#=> Kernel#caller(omit_from_start=1)
# Returns the current execution stack.
# An array containing strings in the form “file:line” or “file:line: in `method'”
# Has an optional start parameter with the number of initial stack entries to omit from the result.
# when omit=0 it will also show the current file:line:method where caller() was called
# Else
begin
puts "in body"
rescue
puts "in rescue"
else
puts "in else"
ensure
puts "in ensure"
end
puts "after end"
#=> in body
#=> in else
#=> in ensure
#=> after end
# Be specific when eating exceptions
# Antipattern
begin
# ...
rescue Exception
end
# Namespace your own exceptions
module MyLibrary
class Error < StandardError; end
end
# Raising Exceptions Require Extra Resources
def fib(n)
return n if n < 2
vals = [0, 1] n.times do
vals.push(vals[-1] + vals[-2])
end
return vals.last
end
def fib_raise(n)
return n if n < 2
vals = [0, 1]
i=0
loop do
vals.push(vals[-1] + vals[-2]) i += 1
raise if i >= n
end
rescue RuntimeError
return vals.last
end
require ’benchmark’
Benchmark.bm(10) { |bm|
bm.report("fib") { 1000.times { fib(100)} } #=> 0.073168
bm.report("fib_raise") { 1000.times { fib_raise(100) } } #=> 0.111309
}
# Alternatives to exceptions
# Multiple return values
#Array
def foo
result = 42
success = true
[result, success]
end
result, success = foo
puts "#{success ? ’Succeeded’ : ’Failed’}; result: #{result}"
# Struct
def foo
result = 42
success = true
OpenStruct.new(:result => 42, :status => :success)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment