Displaying articles with tag

L'uso di "strumenti agili" in Rails

Posted by carlos, Wed Jul 02 11:30:00 UTC 2008

La console

Un'attività che spesso emerge consiste nel provare alcune funzionalità in un file a parte, ed entrare in un ciclo edita-il-file e ricarica-la-pagina-nel-browser (alzi la mano chi non lo ha mai fatto!). Tutto ciò funziona, ma io lo trovo tremendamente macchinoso.... quindi quando posso lo evito volentieri. Come?

In Rails c'è la comodissima console che ci permette di accedere all'ambiente del framework senza la necessità di editare view (inserendo dump vari), o modificare il flusso delle informazioni all'interno dei controller.

Per lanciare la console (da linea di comando, all'interno della directory della nostra applicazione):

1
 $ script/console

possiamo inoltre specificare l'environment da caricare (per default è development):

1
 $ script/console [development | test | production]

E ci troviamo all'interno di una sessione Irb:

1
2
 >>  Post.all
  => []

all'interno della quale è possibile inserire codice ruby che opera, ad esempio, con il data base specificato. Per uscire dalla console è sufficiente un exit oppure un quit.

Vi propongo alcuni tips, in ordine sparso, sulla console:

  • Specificando l'opzione -s (--sandbox) apriamo la console in modalità sandbox: ogni cambiamento che apportiamo al database verrà eliminato all'uscita della console stessa (in pratica viene lanciata una transazione all'apertura della console ed in relativo rollback all'uscita)

  • Per ispezionare un oggetto può essere molto comodo farlo attraverso un dump nel formato YAML:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
      >> my_post = Post.find(:first)
      >> # analogamente possiamo usare .to_yaml
      >> y my_post 
      --- !ruby/object:Post 
      attributes: 
        updated_at: 2007-12-08 13:23:25
        body: Lorem ipsum dolor sit amet, consectetur adipisicing...
        title: My first post here!
        id: "1"
        created_at: 2007-12-08 13:23:25
      attributes_cache: {}
           

  • Quando cambiamo i modelli (in apps/models/) e vogliamo che tali modifiche siano riflesse all'interno della console attiva è sufficiente lanciare il comando reload!.

  • Esiste il tab completion anche sui metodi dei nostri modelli (almeno dopo averli utilizzati la prima volta).

  • Per "pulire" il contenuto dello schermo è sufficiente un CTRL+l oppure un COMMAND+k.

Inoltre, a partire dalla versione 2.1 di Rails, è stato introdotto un nuovo script: dbconsole. E' molto comodo, poiché apre una sessione verso il database (è possibile anche indicare su quale ambiente: development, test, production) evitandoci di digitare ogni volta username, password e nome del database.

Il debugger

Un altro utile strumento è rappresentato dal debugger (che ha preso il posto dei vecchi breakpoints presenti in Rails 1.2.x). Grazie ad esso possiamo inserire dei marcatori all'interno del flusso di istruzioni del controller, lavorare con il browser fino al punto in cui viene incontrato un marcatore e quindi utilizzare una sorta di sessione Irb per per ispezionare i valori delle variabili "dietro le quinte".

Suona complicato? Noooo... vediamo un esempio.

Se non è già installata, occorre la gemma opportuna:

1
 # gem install ruby-debug

Poi occorre lanciare in server in modalità debugger:

1
 $ ruby script/server --debugger

Ora supponiamo di avere questa action nel controller PostController:

1
2
3
4
5
6
7
8
9
10
11
  def update
    @post = Post.find(params[:id])
    debugger
  
    if @post.update_attributes(params[:post])
      flash[:notice] = 'Post was successfully updated.'
      redirect_to :action => 'show', :id => @post
    else
      render :action => 'edit'
    end
  end  

Inserendo l'istruzione debugger diciamo al server di interrompersi non appena raggiunge quel punto nel flusso delle istruzioni.

Nella nostra applicazione il metodo update viene invocato quando salviamo l'editing di un post, ovvero il form presente nell'HTML ha come azione update.

Quando inviamo i dati dal form al server, il browser si blocca in attesa di una risposta (es: lo sfondo blu di Safari nella barra dell'url non scorre):

A questo punto nel terminale dove è in esecuzione il server precedentemente avviato si apre una sessione del debugger (molto simile ad Irb), che presenta un prompt del genere:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  (rdb:53) y @post
  --- !ruby/object:Post 
  attributes: 
    updated_at: 2007-12-08 13:24:50
    title: sddfdsfifjd
    body: 
    id: "4"
    created_at: 2007-12-08 13:24:50
  attributes_cache: {}

  nil
  (rdb:53) @post.title = 'nuovo titolo'
  "nuovo titolo"
  (rdb:53)

Come vedete è possibile accedere al contenuto delle variabili di istanza del controller (in pratica è come se ci trovassimo all'interno dell'action invocata). Una volta "soddisfatti" possiamo dire al server di continuare con il processamento della richiesta tramite il comando cont: torneranno ad essere visualizzate le consuete informazioni di log finché il controller non incontrerà un'altra istruzione debugger... e così via.

Il debugger contiene diversi comandi, che vi invito ad approfondire:

1
2
3
4
5
6
  Type 'help <command-name>' for help on a specific command

  Available commands:
  backtrace break catch cont delete display down eval exit finish frame 
  help irb list method next p pp quit reload restart save script set 
  step thread tmate trace undisplay up var where  

Con ciò concludo la panoramica sul debugger.

Parlando di debug e console mi viene in mente che spesso nel codice inseriamo commenti "opportuni" per indicare che c'è qualcosa da fare, ottimizzare, rivedere, etc. Il problema sta poi nell'avere una lista riassuntiva di tutti questi commenti (sparsi tra i vari controller, models, etc).

Un esempio tanto per chiarire:

1
2
3
4
5
6
7
8
9
10
11
  def update
    @post = Post.find(params[:id])
    # FIXME non salva come dovrebbe
    if @post.update_attributes(params[:post])
      flash[:notice] = 'Post was successfully updated.'
      redirect_to :action => 'show', :id => @post
    else
      render :action => 'edit'
    end
    # TODO prevedere altri controlli?
  end    

Nulla di più immediato grazie ai seguenti task rake:

1
2
3
4
5
6
7
  # mostra tutti i commenti del tipo TODO, FIXME e OPTIMIZE
  $ rake notes
  
  (in /Users/pecchia/Desktop/blog_rails20)
  app/controllers/posts_controller.rb:
    * [ 64] [FIXME] non salva come dovrebbe
    * [ 71] [TODO] prevedere altri controlli?

Oppure possiamo elencarli in maniera più selettiva:

1
2
3
  $ rake notes:fixme
  $ rake notes:optimize
  $ rake notes:todo

Conclusioni

Spero che questo panoramica su console e debugger sia utile o, almeno, che stimoli la vostra curiosità. Avere degli strumenti semplici può farci risparmiare molto tempo... e pazienza. Buon lavoro!

51 comments | Filed Under: Libreria Linguaggio Rails Snippet | Tags: