2011-05-31 22 views
15

Decir que tengo un bucle en mi código que llama al carriles depurador un par de vecesCómo detener el depurador rieles de la solicitud actual

def show 
    animals = ['dog', 'cat', 'owl', 'tiger'] 
    for animal in animals 
    debugger 
    # do something else 
end 

Suponiendo que empecé mi servidor con la opción --debugger, cuando esta página es visto, el depurador se detendrá en cada ejecución del ciclo.

puedo escribir cont cada vez que se detenga lo que la solicitud continúa, pero eso es tedioso, especialmente si no estamos hablando sobre ello a aparecer 4 veces como en este ejemplo, pero 400. ¿Hay una manera de dejar el el depurador continúa sin detenerse en cada punto del ciclo?

Mi solución actual es reiniciar el servidor, pero eso lleva mucho tiempo.

+1

"Parar después de continuar pausando" es una expresión complicada. Lo arreglé en consecuencia. – sawa

Respuesta

16

sólo hay que poner las condiciones de la cuenta de depurador de modo que sólo se detiene cuando lo desee a, por ejemplo:

debugger if animal == 'tiger' 

o si, por ejemplo, desea examinar el código sólo en bucle 384:

animals.each_with_index do |animal, i| 
    debugger if i == 384 
    # do something 
end 

o poner en una variable que le permitirá continuar ad hoc:

continue_debugger = false 
animals.each do |animal| 
    debugger unless continue_debugger 
    # in the debugger type `p continue_debugger = true` then `c` when done 
end 
+0

esta es una buena solución, pero realmente no responde mi pregunta. A veces quiero inspeccionar 1, 2 o 10 entradas antes de detener la depuración, así que estoy buscando un comando para detener la depuración de la solicitud actual (es decir, dejar que la página continúe cargándose). ¿Sabes de algo así? ¡Gracias! –

+0

+1 para la solución 'ad hoc' - asegúrese de mirar el comentario. Dado que puede establecer variables para su código como un todo dentro de la sesión de depuración, como si fuera una sesión irb, este _ le permitirá elegir continuar después de un número arbitrario de paradas. – Matt

+0

uno corregido a la variable 'continue_debugger' - SE SALDRÁ del alcance en ciertas situaciones, así que seguí adelante y puse un signo' @ 'delante para asegurarme de que esté accesible independientemente del alcance. ¡Esta es la solución más fácil! +1 –

12

poner su debugger en algún lugar antes de la iteración, luego configure un punto de interrupción dentro de la iteración que luego puede borrar más adelante.

Ejemplo:

def index 

    debugger 

    @things = Thing.all 
    @things.each do |thing| 
    # ... something you want to check out in the debugger 
    thing.some_calculation 
    end 
end 

Al entrar en el depurador, establecer un punto de interrupción en el interior:.

b app/controllers/things_controller.rb:42 

(donde 42 es el número de línea que desea romperse en, como thing.some_calculation anterior Tenga en cuenta que tiene que ser una línea de código ejecutable - comentarios, las líneas en blanco no funcionarán). El depurador mostrará un número de punto de interrupción y la ubicación:

Breakpoint 1 at .../app/controllers/things_controller.rb:42 

Ahora, cada vez de continuar, haremos una parada en el punto de interrupción. Cuando haya terminado y desea completar la solicitud, eliminar el punto de interrupción:

delete 1 

continuar una vez más, y va a completar la solicitud!

+0

¡Muchas gracias! Si bien esto es mucho más limpio, encontré que la solución de Mori es un poco más rápida de implementar. ¡Ojalá pudiera premiar a todos aquí con la recompensa! –

5

Parece que en la fuente de ruby-debug, la llamada a debuggersiempre detiene la ejecución cada vez que se golpea. Entonces, una solución es hacer lo que Mori sugirió en su solución 'ad-hoc', para hacer un condicionamiento alrededor de la llamada al depurador que pueda modificar dentro de la sesión del depurador, de modo que evite llamar al debugger. Esta es probablemente la mejor solución, y lo que yo haría a menos que tenga problemas de pureza persistentes con el código involucrado.

Si realmente quiere sólo para hacer esto sin alguna condición externa y dentro de la misma sesión del depurador, que es posible.Lo que tienes que hacer es establecer un punto de interrupción en el código en sí mismo, entonces se puede eliminar ese punto de interrupción en el depurador cuando se dispara:

require 'rubygems' 
require 'ruby-debug' 

Debugger.start 
Debugger.add_breakpoint(__FILE__, __LINE__ + 2) 
while true do 
    puts "Hi" 
    puts "mom" 
end 
Debugger.stop 

Esto produce este tipo de interacción:

Breakpoint 1 at debug_test.rb:10 
debug_test.rb:10 
puts "Hi" 
(rdb:1) c 
Hi 
mom 
Breakpoint 1 at debug_test.rb:10 
debug_test.rb:10 
puts "Hi" 
(rdb:1) c 
Hi 
mom 
Breakpoint 1 at debug_test.rb:10 
debug_test.rb:10 
puts "Hi" 
(rdb:1) info b 
Num Enb What 
    1 y at ./debug_test.rb:10 
     breakpoint already hit 3 times 
(rdb:1) del 1 
(rdb:1) c 
Hi 
mom 
Hi 
mom 
Hi 
mom 

. ..y así.

De esta manera, está configurando el punto de interrupción en el código y luego eliminándolo cuando haya terminado. Tenga en cuenta que cada vez que se llame a la línea Debugger.add_breakpoint, volverá a establecer el punto de interrupción, por eso es que está fuera del ciclo y señala 2 líneas hacia abajo. Esta técnica se puede extraer fácilmente al require, una secuencia de comandos que establece el punto de interrupción solo al cargar el servidor: diablos, podría escribir una clase de marco completo para controlar el módulo de depurador como lo desee. Por supuesto, si fue tan lejos, simplemente crearía una clase singleton que lo ayuda a implementar la solución ad-hoc de Mori y lo hace o no-no llama a la declaración del depurador.

+0

¡Muchas gracias por la elaborada respuesta! Creo que la solución de Mori es un poco más fácil de implementar, pero me gustaría poder elegir cada respuesta aquí como la correcta. Tu tiempo es muy apreciado, Matt :) –

0

Tengo otra respuesta a esta: establezca @debug en la clase que desea depurar. De esa manera usted puede hacer:

if (@debug && (the_condition)) then debugger end 

o

debugger unless [email protected] 

continuación, cuando haya terminado con el depurador simplemente @debug = false y c.

Sin embargo, no estoy muy satisfecho con las "paradas difíciles" del depurador en el código en vivo. Este es el tipo de cosas que pueden registrarse accidentalmente y olvidarse hasta que se rompa algo. El @debug ciertamente caería bajo eso también. Para ese fin, creo que mi solución ideal usaría Matt's idea y una secuencia de comandos que configura un punto de interrupción dentro del objeto cuando se crea el objeto. De esta forma tendrías la depuración que deseas pero no tendrías ningún código en el control de código fuente que sea específicamente para el desarrollo. Actualizaré esta respuesta si encuentro tal solución.

1

me ocurrió otra respuesta a esta hoy que me gusta aún mejor:

debugger unless @no_debug

uso que en cada línea que tiene una parada depurador. Cuando quiera dejar de detenerse, simplemente configure @no_debug en algo.

+0

Me gusta mucho – superluminary

0

Siempre puede comentar la llamada debugger desde su código y luego escriba reload en su sesión de depuración. Luego solo cont una vez y la solicitud continuará sin activar una sesión de depuración.

Como está en modo de desarrollo, puede agregar la llamada debugger nuevamente y se activará correctamente.

0

Poniendo esto aquí como una alternativa ya que esta pregunta apareció primero en mis propias búsquedas. Digamos que tiene un fragmento de código que no funciona en una circunstancia específica, pero funciona de otro modo, y tiene una gran cantidad de pruebas que lo hacen, pero una prueba específica que falla.Es un PITA tener que escribir continuamente continue en la consola de depuración hasta llegar a la prueba de que realmente desea depurar, por lo que comenzó a utilizar esta convención:

En su código:

def some_common_function 
    debugger if defined? ::ASDF 
    # do something 
end 

Luego, en su prueba:

should "do this thing that it isn't doing under a specific circumstance" do 
    # setup the specific situation 
    ::ASDF = true 
    # your tests 
end 
0

Si quiero el control de nuevo, acabo de hacer

eval return 

y saldré de la función que se está ejecutando actualmente, lo que generalmente me devolverá al indicador IRB [consola de rieles].

Cuestiones relacionadas