Catching and examining exceptions in a IRB session

When developing with Ruby, I usually spend a lot of time inside a IRB session. You can test little helper functions you are using, etc, etc.

Sometimes, you want to test one function that is not supposed to throw an exception, but is doing so. And the backtrace shows you that the error is buried very deeply in your code.

  >> testit!
  ArgumentError: comparison of String with Array failed
	from /code/proj/lib/subarray.rb:18:in `>'
	from /code/proj/lib/subarray.rb:18:in `is_subarray_of?'
	from /home/gaizka/usr/ruby/gem_repository/gems/activerecord-2.1.1/lib/active_record/attribute_methods.rb:211:in `each_with_index'
	from /code/proj/lib/subarray.rb:13:in `each'
	from /code/proj/lib/subarray.rb:13:in `each_with_index'
	from /code/proj/lib/subarray.rb:13:in `is_subarray_of?'
	from /code/proj/lib/algorithm.rb:44:in `have_them_all'
	from /code/proj/lib/algorithm.rb:44:in `select'
	from /code/proj/lib/algorithm.rb:44:in `have_them_all'
	from /code/proj/lib/algorithm.rb:97:in `deep_search'
	from /code/proj/lib/algorithm.rb:96:in `each'
	from /code/proj/lib/algorithm.rb:96:in `deep_search'
	from ./test/test-algorithm.rb:243:in `testit!'
	from (irb):1

Enter Post-morting debugging wirh ruby-debug.

In that link show you how to use it. I have added this little function to my $HOME/.irbrc, so it’s easier to use it:

 
def with_post_mortem
  Debugger.start
  Debugger.post_mortem do 
    yield
  end
  Debugger.stop
end

Now you can do:

>> with_post_morten { testit! }
/code/proj/lib/subarray.rb:18
while other_idx < other.size && ele > other[other_idx]
(rdb:post-mortem) where
--> #0 > at line /code/proj/lib/subarray.rb:18
    #1 each_with_index at line /code/proj/lib/subarray.rb:13
    #2 is_subarray_of?(other#Array) at line /code/proj/lib/subarray.rb:13
    #3 have_them_all at line /code/proj/lib/algorithm.rb:44
    #4 have_them_all(product_list#Array, provider#Array) at line /code/proj/lib/algorithm.rb:44
    #5 [] at line /codeg/proj/lib/algorithm.rb:97
    #6 size(product_list#Array, stocks#Array) at line /code/proj/lib/algorithm.rb:96
    #7 testit! at line test/pruebas.rb:243
    #8 irb_binding at line (irb):3
    #9 with_post_morten at line /home/gaizka/.irbrc:184

And now, you have all the power of ruby-debug: going up in the backtrace, inspecting values everywhere, … ¡¡anything!!

(rdb:post-mortem) l=
[12, 14] in /code/proj/lib/subarray.rb
   12      other_idx = 0
=> 13      self.each_with_index do |ele, idx|
   14
(rdb:post-mortem) p self
["A0000014", "A0000019", "A0000020", "A0000026", "A0000030"]
(rdb:post-mortem) p other
[["A0000014"], ["A0000019"], ["A0000020"], ["A0000026"], ["A0000030"]]
(rdb:post-mortem) up
#2 is_subarray_of?(other#Array) at line /code/proj/lib/subarray.rb:13
(rdb:post-mortem) up
#3 have_them_all at line /code/proj/lib/algorithm.rb:44
(rdb:post-mortem) l=
[43, 45] in /code/proj/lib/algorithm.rb
   43    
=> 44    having_all = providers.select{ |provider| product_list.is_subarray_of?(provider.products) }
   45

Hope this is helpful to someone!!

Discussion Area - Leave a Comment