Interceptando y examinando excepciones en una sesión de IRB

Cuando estás desarrollando con Ruby, generalmente (yo al menos), pasas bastante tiempo dentro de una sesión de IRB. Vas probando pequeñas funciones que has escrito, exploras una API de otro, etc, etc.

A veces, quieres probar una función que se supone que debería funcionad, pero está lanzando una excepción. Y el backtrace te muestra que el error está demasiado metido dentro del código como para hacer debug paso a paso.

  >> 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

Para estas cosas, viene muy bien el debug post-mortem con ruby-debug.

En la página indicada te enseñan como utilizarlo. Puedes añadir este par de líneas a tu $HOME/.irbrc, de manera que es más fácil de utilizar:

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

Con esto, puedes hacer:

>> 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

Y ahora, tienes todo el poder de ruby-debug: subir/bajar en el backtrace, inspeccionar los valores en cualquiera de los niveles … ¡¡cualquier cosa!!

(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

¡Espero que esto le sea útil a alguien!

Discussion Area - Leave a Comment