lunes, 26 de enero de 2009

Debugging a Rails Application

Cuando estamos desarrollando una App, es muy recomendable depurar o debugearla para ver por ejemplo que valor toma una variable en un determinado momento. O para danos cuenta de que no está tomando ninguno...

De lo que he mirado por el momento sobre el tema de debug (poner a punto) el código, esto es con lo que me quedo:
  1. <%= debug @post %>: Es como un echo de PHP, pero mejor porque te imprime toda la variable de instancia(@post) en la vista.
  2. <%= [1, 2, 3, 4, 5].inspect %> # [1, 2, 3, 4, 5] Útil para imprimir hash y array como string en la vista.
  3. logger.debug "Person attributes hash: #{@person.attributes.inspect}": Esto también esta bien, por ejemplo te puedes dejar recaditos en el controlador, y cuando hagas SCRIPT/SERVER, los veras por el terminal (ej.: esto debería de dar...)
  4. Ruby-debug: Es una gema que nos permite parar la App y meternos dentro de nuuestro código, saber el valor de las variables en ese punto de ejecución, establecer breakpoints,...Ahora lo voy a explicar con un poco más de detalle
Ruby-debug
Lo primero que tenemos que hacer es instalar la gema ruby-debug:
sudo gem install ruby-debug

Lo segundo que debemos de hacer es poner la palabra debugger en la línea del código donde queramos parar.

Después lo que hay que hacer es iniciar el servidor : script/server --debugger
(de momento ruby-debug sólo funciona con mongrel y webrick)

Nota el uso de --debugger. Con esto le estamos diciendo al servidor que arranque en modo debugeo:

Una vez que el servidor haya arrancado, tenemos que navegar por nuestra app e ir a la acción en la que hemos colocado
la palabra debugger. Ej.: Si lo has puesto en el metodo new del controlador historias, tendrás que intentar pulsar el link que te lleva a crear una nueva historia
vamos que te lleva a la acción new. Entonces notaras que el navegador se queda parado y no llegas a ver la pantalla con la vista new.html.erb.

Ahora es momento de que vayas al terminal en el que iniciaste el servidor:
script/server --debugger
Deberías de ver que el Terminal no sigue mostrando información y permanece a la espera. Deberías de ver algo así:
(rdb:13)

Esto quiere decir que el servidor se ha parado y que ahora puedes usar los comandos que te da ruby-debug.

Si más muestro los comandos que a mi me han parecido más útiles:

help
: te muestra todos los comandos de ruby-debug
help
: te muestra ayuda de un comando en concreto.
list:
te muestra tu código. Por donde esta el debugger pasando en ese momento.
backtrace o where
: Muy bueno para aprender. Te muestra todos los archivos de rails que participan en la realización de la petición:
ej.: de backtrace:
#0 PostsController.index
at line /PathTo/project/app/
controllers/posts_controller.rb:6

#1 Kernel.send
at line /PathTo/project/vendor/rails/
actionpack/lib/action_controller/base.rb:1175
#2 ActionController::Base.
perform_action_without_filters
at line /PathTo/project/vendor/rails/
actionpack/lib/action_controller/base.rb:1175
#3 ActionController::Filters::
InstanceMethods.call_filters(chain#ActionController::Fil...,...)
at line /PathTo/project/vendor/rails/
actionpack/lib/action_controller/filters.rb:617
...

En una petición de New a mi controller intervenían 29# archivos
frame n
: Para saltar a uno de esos 29# archivos y ver como se ejecuta el código de Rails y el tuyo y ver que variables hay en juego.
instance_variables
: con este te saca un Array con todas las variables de instancia definidas en ese momento...útil
var instance :
Muestra las variables de instancia de un objeto:
ej.:

(rdb:9) var instance Post.new
@attributes = {"updated_at"=>nil, "body"=>nil, "title"=>nil, "published"=>nil, "created_at"...
@attributes_cache = {}
@new_record = true

En este ejemplo se ven las variables de instancia del objeto (Post.new)
display
: Le dices, muestrame esta variable (por ejemplo @post) según avanzo por el código (con NEXT por ejemplo) y cada vez que avanzas te va diciendo
el valor que va tomando @post. tambien se le puede decr que te lo deje de mostrar undisplay @post.
step
: Avanza por el código como next
pero la diferencia es que next avanza linea por linea y step avanza de bloque de ejecución en bloque de ejecución.

Hay tres formas de poner breakpoints
break
: La palabra break y un nº de linea. P.ej.: si estoy en la linea 3 y quiero parar el código en la nº 5, pongo break 5
break file:line [if expresion]
: Pones la palabra break y después un path a un archivo (ej.: /Users/web/RoR/App/rails2/restblog/app/models/user.rb) aunque
nuestro debugeo haya empezado en un controller, podemos apuntar a cualquier archivo de nuestra App. Despues de los dos puntos hay que especificar el nº de
linea de ese archivo en el que ponemos el break. Lo último no lo he usaro
[if expresion], pero sirve para poner una condición al break, y si se cumple, se ejecuta,
y si no, pasa del break.


break class(.|#)method [if expression]:
pone el break en el metodo de clase(.) o metodo de instancia de esa clase(#):
"set breakpoint in method (. and # for class and instance method respectively) defined in class. The expression works the same way as with file:line.
"
Lo que yo
entiendo lo muestro con un ejemplo:
Tengo un archivo User.rb con un metodo
latest_post definido en el que pilla los últimos 4 post de ese usuario
def latest_post
posts.find(:all, :order => 'id DESC', :limit => 4)
end

Supongamos que yo inicio mi debugger en el controller del modelo User (users_controller.rb). en el metodo index de este controller:


def index
debugger
@users = User.find(:all)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @users }
end
end
el método que hemos definido en el modelo user (en user.rb) -->
latest_post

Lo usamos en la vista index del modelo User (index.html.erb)

<% for user in @users %>
<%= user.latest_post_title %>
<% end %>
vale, ¿situados? ahora si queremos meter un break haremos:
(rdb:5) break User#latest_post

Ahora cuando le demos a cont para continuar el código se nos parara en user.rb:line 4 que es donde hemos definido el metodo en el modelo.

Una vez puestos los break hay 4 comandos que son útiles:
info breakpoints
: te dice los breaks que has puesto ej.:
(rdb:5) info breakpoints
Num Enb What
1 y at users_controller.rb:15
2 y at User:latest_post_title

En este caso he puesto 2 break
enable breakpoints:
Autoexplicativo, habilita los todos los break
disable breakpoints: Autoexplicativo, deshabilita los todos los break
delete n: Borra el break n cuyo nº sabes con info breakpoints
Creo que está bien ruby-debug. A mi me puede hacer la vida más fácil.


Unos links útiles para iniciarte en el debugeo de una App.
De ellos he sacado la información que he puesto en este post:


[1]
http://guides.rubyonrails.org/debugging_rails_applications.html
[2]
http://www.sitepoint.com/article/debug-rails-app-ruby-debug/

No hay comentarios:

Publicar un comentario