#44 Debugging RJS
RJS rende semplice la scrittura di applicazioni Rails AJAX-enabled, tuttavia i bachi possono ancora nascere. In questo episodio mostriamo come fare il debug sia lato server, sia lato client degli errori. L’applicazione scritta nell’ultimo episodio permetteva ai clienti di aggiungere opinioni sui prodotti mediante una form che usava AJAX, ma ora non funziona. Quando si preme sul pulsante per provare ad aggiungere un’opinione, non succede nulla. Questo significa che c’è un errore da qualche parte durante la chiamata AJAX: o la richiesta non viene inviata correttamente, oppure avviene un errore sul server che rende invalida la risposta o che addirittura fa in modo che non arrivi alcuna risposta al client. Anomalie del genere possono essere difficili da tracciare dal momento che il browser non mostra messaggi di errore e quindi non si ha nemmeno un indizio sul punto da cui iniziare la ricerca del problema.
La pagina del prodotto che non funziona.
Tracciare la chiamata
Il primo passo per il debug del problema consiste nel controllare il sorgente della pagina. Guardiamo la sezione <head>
per assicurarci innanzitutto che i file JavaScript necessari siano referenziati:
<head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <link href="/stylesheets/ep44.css?1237493400" media="screen" rel="stylesheet" type="text/css" /> <script src="/javascripts/prototype.js?1237114650" type="text/javascript"></script> <script src="/javascripts/effects.js?1237114650" type="text/javascript"></script> <script src="/javascripts/dragdrop.js?1237114650" type="text/javascript"></script> <script src="/javascripts/controls.js?1237114650" type="text/javascript"></script> <script src="/javascripts/application.js?1237114650" type="text/javascript"></script> <title>Episode 44: Debugging RJS</title> </head>
I file JavaScript referenziati nella sezione <head>della nostra pagina.
Le librerie Prototype e script.aculo.us sono correttamente referenziate. Allora diamo un’occhiata al tag di apertura della form per assicurarci che la richiesta AJAX sia richiamata al submit della form:
<form action="/products/1/reviews" class="new_review" id="new_review" method="post" onsubmit="new Ajax.Request('/products/1/reviews', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">
Ciò che controlliamo è che ci sia la richiesta AJAX e che l’URL invocato sia corretto. Il nostro codice sembra a posto fino ad ora; il JavaScript nell’attributo onsubmit create una nuova Ajax.Request e l’URL è quello giusto per creare una nuova opinione.
Dato che il codice generato per il client sembra a posto, non ci resta che ricercare il problema lato server. Il log di sviluppo è in grado di dirci se è stata fatta una chiamata AJAX. Lanciamo il comando tail
sul log e proviamo a fare il submit di un’altra richiesta:
Processing ReviewsController#create (for 127.0.0.1 at 2009-03-19 21:17:50) [POST] Parameters: {"commit"=>"Add comment", "review"=>{"name"=>"Bob", "content"=>"Wow!"}, "product_id"=>"1", "authenticity_token"=>"4cncFdRcYuinYVNWj3uGZTPuvx4VXM7gBCRCMOLt4fw=", "_"=>""} Review Create (0.4ms) INSERT INTO "reviews" ("name", "updated_at", "product_id", "content", "created_at") VALUES('Bob', '2009-03-19 21:17:50', 1, 'Wow!', '2009-03-19 21:17:50') Rendering reviews/create Rendered reviews/_review (1.3ms) Product Load (0.3ms) SELECT * FROM "products" WHERE ("products"."id" = 1) SQL (0.2ms) SELECT count(*) AS count_all FROM "reviews" WHERE ("reviews".product_id = 1) ActionView::TemplateError (undefined method `pluralized' for #<ActionView::Base:0x221b66c>) on line #2 of app/views/reviews/create.rjs: 1: page.insert_html :bottom, :reviews, :partial => 'review', :object => @review 2: page.replace_html :reviews_count, pluralized(@review.product.reviews.size, 'Review') 3: page[:new_review].reset 4: page.replace_html :notice, flash[:notice] 5: flash.discard
L’errore RJS nel log di sviluppo.
Non appena clicchiamo sul pulsante, appare sui log un messaggio di errore. L’azione corretta (ReviewsController#create
) viene effettivamente chiamata e l’opinione viene inserita nella tabella reviews del database. Poi viene chiamato il file RJS ed è qui che avviene l’errore. Il log mostra che nel nostro file RJS viene tentata l’invocazione di un metodo non definito, pluralized
.
Se guardiamo al nostro file RJS troveremo la linea di codice che causa l’errore. Il metodo dovrebbe chiamarsi pluralize e non >pluralized. Correggiamo il codice e vediamo se la correzione è risolutiva:
page.replace_html :reviews_count, pluralize(@review.product.reviews.size, 'Review')
L’opinione è ora aggiunta.
La nostra modifica ha corretto l’errore e ora la nostra form è inviata correttamente. Giusto per essere sicuri diamo un’altra occhiata alla fine del log di sviluppo: dovremmo non trovare errori e vedere che la richiesta si è completata con successo:
Processing ReviewsController#create (for 127.0.0.1 at 2009-03-19 22:06:40) [POST] Parameters: {"commit"=>"Add comment", "review"=>{"name"=>"Fry", "content"=>"This is great!"}, "product_id"=>"1", "authenticity_token"=>"4cncFdRcYuinYVNWj3uGZTPuvx4VXM7gBCRCMOLt4fw=", "_"=>""} Review Create (0.4ms) INSERT INTO "reviews" ("name", "updated_at", "product_id", "content", "created_at") VALUES('Fry', '2009-03-19 22:06:40', 1, 'This is great!', '2009-03-19 22:06:40') Rendering reviews/create Rendered reviews/_review (0.1ms) Product Load (0.3ms) SELECT * FROM "products" WHERE ("products"."id" = 1) SQL (0.2ms) SELECT count(*) AS count_all FROM "reviews" WHERE ("reviews".product_id = 1) Completed in 22ms (View: 10, DB: 1) | 200 OK [http://localhost/products/1/reviews]
E’ stato un bug piuttosto semplice da sistemare, ma ci ha dato modo di vedere come procedere nella ricerca di errori simili durante le varie fasi di chiamata AJAX.
Errori lato client
Talvolta una richiesta AJAX fallisce, ma i file di log mostrano che il codice lato server viene eseguito correttamente. In questi casi occorre un buon debugger JavaScript, ed uno veramente buono è Firebug per Firefox. Firebug può essere installato direttamente dal sito del plugin alla stessa maniera di qualunque altra estensione Firefox. Una volta installato, può essere usato per fare il debug HTML, CSS e JavaScript, incluse le richieste AJAX.
Firebug è disabilitato di default.
Firebug si attiva cliccando l’icona dello scarafaggio nella status bar. Di default è disabilitato per il server corrente. Per abilitarlo, spuntiamo tre checkbox e premiamo il pulsante “Apply”. Una volta abilitato, aggiungiamo un’altra opinione nella nostra pagina e vediamo cosa compare nella console Firebug:
La console ci mostra che la nostra richiesta AJAX è stata inviata ed ha ottenuto in risposta un codice HTTP 200, per cui è andata a buon fine. Se fosse fallita la richiesta, in generale vedremmo la linea di testata rossa e uno status HTTP pari a 500. Sotto ci sono tre tab che mostrano ciò che è stato inviato negli header e nel body della richiesta e quello che è stato rispedito indietro nella risposta. Nel tab sopra possiamo vedere i contenuti dei campi di form che sono stati mandati:
Nel tab ‘Response’ cè il JavaScript generato dal nostro template RJS. La nostra chiamata Ajax valuterà questo script quando ritorna indietro dal server ed è proprio questo script che causa l’aggiornamento della pagina ed il reset della form. Essere in grado di vedere il JavaScript che sta per essere processato è incredibilmente utile, perchè ci rende in grado di debuggare molto più facilmente che non facendolo mediante alert
statement.
Ciò, detto, i messaggi di alert hanno ancora la loro utilità. Se un errore viene lanciato dal JavaScript che viene restituito dal server, sarà catturato dal blocco try
/ catch
del codice e un messaggio di alert
sarà mostrato. Vediamo tutto ciò ora, causando deliberatamente un errore cambiando la linea di codice del file RJS che resetta la form, in modo tale che riferisca un id
sbagliato.
Ciò, detto, i messaggi di alert hanno ancora la loro utilità. Se un errore viene lanciato dal JavaScript che viene restituito dal server, sarà catturato dal blocco try
/ catch
del codice e un messaggio di alert
sarà mostrato. Vediamo tutto ciò ora, causando deliberatamente un errore cambiando la linea di codice del file RJS che resetta la form, in modo tale che riferisca un id
sbagliato.
Aggiungendo un’opinione ora causa la comparsa di dei seguenti due alert, il primo che mostra l’errore e il secondo che mostra il codice che lo ha causato.
Per fortuna il messaggio di errore spiega chiaramente che l’errore è avvenuto come conseguenza del fatto che non si è riuscito a trovare un elemento sulla pagina con id
new_reviewXXX
, per cui abbiamo un buon punto di partenza per cercare di intercettare l’errore.
Abbiamo coperto abbastanza argomenti in questo episodio per darvi una buona idea di dove partire per debuggare il codice RJS. Con l’uso combinato di log di sviluppo per il controllo lato server e Firebug per il controllo del codice client avrete sufficienti informazioni per correggere rapidamente qualunque anomalia che possiate incontrare.
=======Abbiamo coperto abbastanza argomenti in questo episodio per darvi una buona idea di dove partire per debuggare il codice RJS. Con l’uso combinato di log di sviluppo per il controllo lato server e Firebug per il controllo del codice client avrete sufficienti informazioni per correggere rapidamente qualunque anomalia che possiate incontrare.
>>>>>>> b97aa6197477c8dd0eb373f63b133400a451886f