¿Cómo depuro los scripts de Ruby?

Copié el siguiente código de Ruby de Internet e hice algunos cambios.

#insert code here 

¡Pero no funciona!

Por favor ayuda. ¿Qué puedo hacer para depurar el progtwig yo solo?

Use Pry ( GitHub ).

Instalar a través de:

 $ gem install pry $ pry 

Luego añade:

 require 'pry' 

en tu progtwig.

  1. En Ruby:

     ruby -rdebug myscript.rb 

    entonces,

    • b : poner punto de quiebre
    • y n(ext) o s(tep) c(ontinue)
    • p(uts) para la visualización

    (como la depuración de perl)

  2. En Rails: inicia el servidor con

     script/server --debugger 

    y agregue debugger en el código.

Como barandilla recomendada: use pry! Solo puedo estar de acuerdo en esto.

pry es una réplica mucho mejor que irb.

Necesitas agregar

 require 'pry' 

a su archivo fuente y luego inserte un punto de interrupción en su código fuente al agregar

 binding.pry 

en el lugar donde quieres echar un vistazo a las cosas (esto es como desencadenar un punto de interrupción en un entorno IDE clásico)

Una vez que su progtwig llegue al

 binding.pry 

línea, serás arrojado directamente a la palanca de respuesta, con todo el contexto de tu progtwig al scope de la mano, para que puedas simplemente explorar todo, investigar todos los objetos, cambiar de estado e incluso cambiar el código sobre la marcha.

Creo que no puedes cambiar el código del método en el que te encuentras actualmente, por lo que lamentablemente no puedes cambiar la siguiente línea para ejecutar. Pero el buen código de Ruby tiende a ser de una sola línea 😉

La depuración mediante el aumento de excepciones es mucho más fácil que entrecerrar a través de print instrucciones de registro de print , y para la mayoría de los errores, en general es mucho más rápido que abrir un depurador IRB como pry o byebug . Esas herramientas no deberían ser su primer paso.


Depuración de Ruby / Rails rápidamente:

1. Método rápido: levante una Exception y luego .inspect su resultado

La manera más rápida de depurar el código de Ruby (especialmente Rails) es hacer una excepción a lo largo de la ruta de ejecución de su código al llamar .inspect en el método u objeto (por ejemplo, foo ):

 raise foo.inspect 

En el código anterior, raise activa una Exception que detiene la ejecución de su código y devuelve un mensaje de error que contiene convenientemente información sobre el objeto / método (es decir, foo ) en la línea que intenta depurar.

Esta técnica es útil para examinar rápidamente un objeto o método ( por ejemplo, ¿es nil ? ) Y para confirmar de inmediato si una línea de código se está ejecutando en absoluto dentro de un contexto dado.

2. Fallback: use un depurador IRB de ruby como byebug o pry

Solo después de tener información sobre el estado de flujo de ejecución de sus códigos, debería considerar pasar a un depurador de Ruby gem, como pry o byebug donde puede profundizar en el estado de los objetos dentro de su ruta de ejecución.


Consejo general para principiantes

Cuando intenta depurar un problema, un buen consejo es siempre: Leer el mensaje de error de @ @ $ ing (RTFM)

Eso significa leer los mensajes de error con cuidado y completamente antes de actuar para que comprenda lo que trata de decirle. Cuando depure, haga las siguientes preguntas mentales, en este orden , al leer un mensaje de error:

  1. ¿A qué clase hace referencia el error? (es decir, ¿tengo la clase de objeto correcta o mi objeto es nil ? )
  2. ¿A qué método hace referencia el error? ( es decir, ¿ es un tipo en el método? ¿Puedo llamar a este método en este tipo / clase de objeto? )
  3. Finalmente, usando lo que puedo deducir de mis dos últimas preguntas, ¿qué líneas de código debo investigar? (recuerde: la última línea de código en el seguimiento de la stack no es necesariamente donde reside el problema.)

En el seguimiento de la stack, preste especial atención a las líneas de código que provienen de su proyecto (por ejemplo, líneas que comienzan con la app/... si está utilizando Rails). El 99% del tiempo el problema es con tu propio código.


Para ilustrar por qué la interpretación en este orden es importante …

Por ejemplo, un mensaje de error de Ruby que confunde a muchos principiantes:

Ejecutas código que en algún punto se ejecuta como tal:

 @foo = Foo.new ... @foo.bar 

y obtienes un error que dice:

undefined method "bar" for Nil:nilClass

Los principiantes ven este error y piensan que el problema es que la bar métodos no está definida . No es. En este error, la parte real que importa es:

for Nil:nilClass

for Nil:nilClass significa que @foo es Nil! @foo no es una variable de instancia Foo ! Tienes un objeto que es Nil . Cuando ve este error, simplemente Ruby intenta decirle que la bar método no existe para los objetos de la clase Nil . (Bueno, ya que estamos tratando de usar un método para un objeto de la clase Foo no Nil ).

Desafortunadamente, debido a la forma en que se escribe este error ( undefined method "bar" for Nil:nilClass ) es fácil undefined method "bar" for Nil:nilClass para que piense que este error tiene que ver con que la bar undefined está undefined . Cuando no se lee atentamente, este error hace que los principiantes vayan cavando por equivocación en los detalles del método de bar en Foo , omitiendo por completo la parte del error que indica que el objeto es de la clase incorrecta (en este caso: nulo). Es un error que se evita fácilmente al leer los mensajes de error en su totalidad.

Resumen:

Siempre lea cuidadosamente el mensaje de error completo antes de comenzar cualquier depuración. Eso significa: siempre compruebe primero el tipo de clase de un objeto en un mensaje de error, luego sus métodos , antes de comenzar a investigar en cualquier stacktrace o línea de código donde piense que el error puede estar ocurriendo. Esos 5 segundos pueden ahorrarle 5 horas de frustración.

tl; dr: no entrecerrar los ojos en los registros de impresión: levantar excepciones en su lugar. Evite los agujeros de conejo leyendo errores cuidadosamente antes de la depuración.

  1. Imprima las variables siempre que sea posible. (Esto se denomina depuración de printf) Puede hacer esto ejecutando

     STDERR.puts x.inspect 

    o

     STDERR.puts "Variable x is #{x.inspect}" 

    Si desea que sea más fácil escribir, puede usar la gem de ejemplo .

  2. Enciende las advertencias Si está ejecutando ruby , ejecútelo con el ruby -w script.rb (por ejemplo, ruby -w script.rb ). Si lo está ejecutando desde irb, y está usando una versión de ruby ​​anterior a 1.9.2, escriba $VERBOSE = true al comienzo de su sesión. Si escribe mal una variable de instancia, una vez que las advertencias estén activadas, obtendrá

    advertencia: variable de instancia @valeus no inicializada

  3. Comprender el concepto de una chuleta binaria (la siguiente cita es de Practices of an Agile Developer )

    Divida el espacio del problema por la mitad, y vea qué mitad contiene el problema. Luego divide esa mitad por la mitad otra vez, y repite.

  4. Si tiene éxito con un corte binario, puede encontrar que hay una sola línea que no hace lo que espera que haga. Por ejemplo

     [1, 2, 3].include?([1,2]) 

    da un valor de false , aunque creas que volverá true . En ese caso, es posible que desee consultar la documentación. Los sitios web para documentación incluyen ruby-doc.org o APIdock . En este último caso, ¿escribirías include? al lado de la lupa cerca de la esquina superior derecha, elija el include? que tiene Array debajo (si no sabes qué clase [1, 2, 3] es, escribe [1, 2, 3].class en irb), y llegas a incluir? (Array) , que describe lo que hace.

    Sin embargo, si la documentación no ayuda, es más probable que obtenga una buena respuesta si puede hacer una pregunta sobre cómo una línea específica no está haciendo lo que debería, en lugar de por qué un guión completo no está haciendo lo que debería. debería.

Todas las otras respuestas ya dan casi todo … Solo un pequeño añadido.

Si desea un depurador más similar a IDE (que no sea CLI) y no tenga miedo de usar Vim como editor, le sugiero el plugin Depurador de Ruby Vim para ello.

Su documentación es bastante sencilla, así que siga el enlace y vea. En resumen, le permite establecer un punto de interrupción en la línea actual en el editor, ver las variables locales en una ventana ingeniosa en pausa, pasar por encima / en – casi todas las características habituales del depurador.

Para mí fue muy agradable usar este depurador de vim para depurar una aplicación de Rails, aunque las capacidades ricas de registrador de Rails casi eliminan su necesidad.

  1. Puedes imprimir tus variables en el camino
  2. Encienda la bandera -w (advertencias)
  3. Use una herramienta como Ruby-Debug

Recomiendo este video para elegir la herramienta adecuada en este momento para depurar nuestro código.

https://www.youtube.com/watch?v=GwgF8GcynV0

Personalmente, destacaría dos grandes temas en este video.

  • Pry es increíble para los datos de depuración, “pry es un explorador de datos” (sic)
  • El depurador parece ser mejor depurar paso a paso.

¡Son mis dos centavos!

Acabo de descubrir esta joya (convierte a Pry en un depurador para MRI Ruby 2.0+)

https://github.com/deivid-rodriguez/pry-byebug

 break SomeClass#run # Break at the start of `SomeClass#run`. break Foo#bar if baz? # Break at `Foo#bar` only if `baz?`. break app/models/user.rb:15 # Break at line 15 in user.rb. break 14 # Break at line 14 in the current file. 

Para depurar fácilmente el script de shell de Ruby, simplemente cambie su primera línea de:

 #!/usr/bin/env ruby 

a:

 #!/usr/bin/env ruby -rdebug 

Luego, cada vez que se muestre la consola del depurador, puede elegir:

  • c para Continuar (a la siguiente Excepción, punto de corte o línea con: debugger ),
  • n para la siguiente línea,
  • w / where mostrar el marco / stack de llamadas,
  • l para mostrar el código actual,
  • cat para mostrar los puntos de captura.
  • h para más ayuda.

Ver también: depuración con ruby-debug , accesos directos clave para la gem ruby-debug .


En caso de que la secuencia de comandos se cuelgue y necesite una lldb , intente usar lldb / gdb como:

 echo 'call (void)rb_backtrace()' | lldb -p $(pgrep -nf ruby) 

y luego verifica tu proceso en primer plano.

Reemplace lldb con gdb si funciona mejor. Prefijo con sudo para depurar proceso no propiedad.

borra todas las cosas

Bienvenido a 2017 ^ _ ^

De acuerdo, entonces, si no te opones a probar un nuevo IDE, puedes hacer lo siguiente de forma gratuita .

Instrucciones rápidas

  1. Instalar vscode
  2. Instale Ruby Dev Kit si aún no lo ha hecho
  3. Instalar extensiones Ruby, ruby-linter y ruby-rubocop para vscode
  4. Instale manualmente las gems que especifica rubyide / vscode-ruby , si es necesario
  5. Configure su launch.json para usar los launch.json "cwd" y "program" usando la macro {workspaceRoot}
  6. Agregue un campo llamado "showDebuggerOutput" y "showDebuggerOutput" en true
  7. Habilite los puntos de interrupción en todas partes en sus preferencias de depuración como "debug.allowBreakpointsEverywhere": true

Instrucciones detalladas

  1. Descargar Visual Studio Code aka vscode ; esto no es lo mismo que Visual Studio . Es gratis, liviano y generalmente considerado positivamente.
  2. Instale el Ruby Dev Kit; debe seguir las instrucciones en su repository aquí: https://github.com/oneclick/rubyinstaller/wiki/Development-Kit
  3. A continuación, puede instalar extensiones a través de un navegador web o dentro del IDE; esto es para dentro del IDE. Si eliges el otro, puedes ir aquí . Navegue a la parte Extensions de vscode; Puedes hacer esto de varias maneras, pero el método más a prueba de futuro probablemente estará presionando F1 y escribiendo e x t hasta que una opción llamada Extensiones: Instalar extensiones esté disponible. Las alternativas son Ctrl Shift x y desde la barra de menú superior, View->Extensions
  4. A continuación, querrás las siguientes extensiones; estos no son 100% necesarios, pero te dejaré decidir qué guardar después de haber jugado un poco:
    • Rubí; autor de extensión Peng Lv
    • ruby-rubocop; autor de extensión misogi
    • ruby-linter; autor de extensión Cody Hoover
  5. Dentro del directorio de la secuencia de comandos de ruby, vamos a hacer un directorio a través de la línea de comandos llamada .vscode y allí solo encontraremos un archivo llamado launch.json donde almacenaremos algunas opciones de configuración.
    • contenidos de launch.json

{ "version": "0.2.0", "configurations": [ { "name": "Debug Local File", "type":"Ruby", "request": "launch", "cwd": "${workspaceRoot}", "program": "{workspaceRoot}/../script_name.rb", "args": [], "showDebuggerOutput": true } ] }

  1. Siga las instrucciones de los autores de la extensión para las instalaciones de gems manuales. Está ubicado aquí por ahora: https://github.com/rubyide/vscode-ruby#install-ruby-dependencies
  2. Probablemente querrás la posibilidad de poner puntos de interrupción donde quieras; no tener esta opción habilitada puede causar confusión. Para hacer esto, iremos a la barra de menú superior y seleccionaremos File->Preferences->Settings (o Ctrl , ) y nos desplazaremos hasta llegar a la sección de Debug . Expanda y busque un campo llamado "debug.allowBreakpointsEverywhere" – seleccione ese campo y haga clic en el pequeño ícono de lápiz y "debug.allowBreakpointsEverywhere" en true .

Después de hacer todas esas cosas divertidas, debería poder establecer puntos de interrupción y depurar en un menú similar a este para mediados de 2017 y un tema más oscuro: enter image description here con todas las cosas divertidas como tu stack de llamadas, visor variable, etc.

El PITA más grande es 1) instalar los prerrequisitos y 2) recordar configurar el archivo .vscode\launch.json . Solo el # 2 debe agregar cualquier equipaje a los proyectos futuros, y puede simplemente copiar una configuración genérica suficiente como la que se menciona arriba. Probablemente haya una ubicación de configuración más general, pero no sé de qué hablar.

A partir de Ruby 2.4.0, es más fácil comenzar una sesión IRB REPL en el medio de cualquier progtwig de Ruby. Coloque estas líneas en el punto del progtwig que desea depurar:

 require 'irb' binding.irb 

Puede ejecutar el código de Ruby e imprimir las variables locales. Escriba Ctrl + D o quit para finalizar el REPL y dejar que el progtwig Ruby siga funcionando.

También puede usar puts p para imprimir valores de su progtwig mientras se está ejecutando.

depuración de printf

Siempre ha habido una controversia en torno a las técnicas de depuración, a algunas personas les gusta depurar mediante declaraciones impresas, otras a profundizar con un depurador.

Sugeriría que pruebes ambos enfoques.

En realidad, uno de los viejos miembros de Unix dijo recientemente que la depuración de printf era una forma más rápida de hacerlo en algunos puntos.

Pero si eres nuevo en algún trabajo y necesitas entender una gran cantidad de código, entonces es realmente útil dar un paso por ahí, poniendo algunos puntos de ruptura aquí y allá, acompañando a la forma en que funciona.

Debería darte una idea de cómo se teje el código.

Si es nuevo en el software de otras personas, podría ayudarlo a avanzar.

Pronto sabrá si lo arreglaron de una manera inteligente, o si eso es solo un montón de mierda.

La madre de todo el depurador es la vieja pantalla de impresión. La mayoría de las veces, probablemente solo desee inspeccionar algunos objetos simples, una manera rápida y fácil es la siguiente:

 @result = fetch_result p "--------------------------" p @result 

Esto imprimirá el contenido de @result to STDOUT con una línea en el frente para una fácil identificación.

Bonificación si usa un marco con capacidad de carga automática / recarga como Rails, ni siquiera tendrá que reiniciar su aplicación. (A menos que el código que está depurando no se vuelva a cargar debido a la configuración específica del marco)

Encuentro que esto funciona para el 90% del caso de uso para mí. También puedes usar ruby-debug, pero creo que es excesivo la mayor parte del tiempo.

Bueno, ruby ​​standard lib tiene un depurador de consola similar a gdb fácil de usar: http://ruby-doc.org/stdlib-2.1.0/libdoc/debug/rdoc/DEBUGGER__.html No es necesario instalar gems adicionales. Los scripts de Rails se pueden depurar de esa manera también.

p.ej

 def say(word) require 'debug' puts word end 

Si está utilizando RubyMine , la depuración de los scripts Ruby es simple y directa.

Supongamos que tiene un script de Ruby hello_world.rb

1. Establecer puntos de interrupción

Establezca un punto de interrupción en la línea 6 como se muestra a continuación.

enter image description here

2. Comience a depurar

Ahora puede iniciar el depurador para ejecutar el script:

enter image description here

enter image description here

3. Inspeccionar variables, etc.

Luego, cuando la ejecución llegue a un punto de interrupción, podrá inspeccionar variables, etc.

enter image description here

Más información para su referencia

  1. Si desea usar RubyMine para realizar la depuración remota , puede hacerlo.
  2. Si desea utilizar RubyMine para raíles de depuración remotos que se ejecutan dentro de una ventana acoplable , también es sencillo.

Hay muchos depuradores con diferentes funciones, en función de las cuales usted elige. Mis prioridades estaban satisfechas con los movimientos de palanca que fue:

  • información rápidamente comprensible sobre cómo usar
  • pasos intuitivos (como caminar fácilmente en bloques)
  • “retroceder” (los movimientos de palanca satisfacen parcialmente la necesidad)