2008-09-20 21 views
7

He aquí los últimos cuadros de una Rubí típica en los carriles de rastreo: application trace http://img444.imageshack.us/img444/8990/rails-lastfew.png¿Cómo puedo obtener los valores fuente y variables en los registros de ruby?

Y aquí están los últimos cuadros de una típica rastreo Nevow en Python: alt text http://img444.imageshack.us/img444/9173/nw-lastfew.png

No es sólo el entorno de web, puede hacer comparaciones similares entre ipython e irb. ¿Cómo puedo obtener más de este tipo de detalles en Ruby?

+0

Oye, los enlaces de imagen están rotos. – alanjds

Respuesta

7

AFAIK, una vez que se ha capturado una excepción, es demasiado tarde para captar el contexto en el que surgió. Si trampa nueva llamada de excepción, se puede usar Binding.of_caller de evil.rb para agarrar el ámbito global del script, y hacer

eval("local_variables.collect { |l| [l, eval(l)] }", Binding.of_caller) 

Pero eso es todo un gran truco. La respuesta correcta es probablemente extender Ruby para permitir una cierta inspección de la pila de llamadas. No estoy seguro de si algunas de las nuevas implementaciones de Ruby lo permitirán, pero sí recuerdo una reacción contra Binding.of_caller porque hará las optimizaciones mucho más difíciles.

(Para ser honesto, no entiendo esta reacción:., Siempre y cuando el intérprete registra información suficiente acerca de las optimizaciones realizadas, Binding.of_caller debe ser capaz de trabajar, aunque tal vez poco a poco)

actualización

Ok, lo descubrí. El código de Longish sigue:

class Foo < Exception 
    attr_reader :call_binding 

    def initialize 
    # Find the calling location 
    expected_file, expected_line = caller(1).first.split(':')[0,2] 
    expected_line = expected_line.to_i 
    return_count = 5 # If we see more than 5 returns, stop tracing 

    # Start tracing until we see our caller. 
    set_trace_func(proc do |event, file, line, id, binding, kls| 
     if file == expected_file && line == expected_line 
     # Found it: Save the binding and stop tracing 
     @call_binding = binding 
     set_trace_func(nil) 
     end 

     if event == :return 
     # Seen too many returns, give up. :-(
     set_trace_func(nil) if (return_count -= 1) <= 0 
     end 
    end) 
    end 
end 

class Hello 
    def a 
    x = 10 
    y = 20 
    raise Foo 
    end 
end 
class World 
    def b 
    Hello.new.a 
    end 
end 

begin World.new.b 
rescue Foo => e 
    b = e.call_binding 
    puts eval("local_variables.collect {|l| [l, eval(l)]}", b).inspect 
end 
Cuestiones relacionadas