Rails e jQuery

Rails + jQueryFin dal suo esordio, Ruby on Rails ha sempre integrato Prototype come framework JavaScript predefinito per la creazione di un nuovo progetto e Scriptaculous come libreria JavaScript per la gestione degli effetti. Rails è stato uno dei primi framework a fondere un linguaggio di programmazione server side come Ruby con uno di scripting come JavaScript, in un modo così elegante da sembrare un tutt'uno. Questo aspetto, impossibile negarlo, è stato uno degli elementi chiave che in passato ha saputo raccogliere l'interesse di molti sviluppatori portandoli a provare il framework.

L'evoluzione dell'uso di JavaScript all'interno di applicazioni web ha portato alla nascita di numerosi framework JavaScript alternativi a Prototype come Dojo, MooTols e jQuery. Proprio quest'ultimo è il protagonista di questo articolo dove vedremo come integrare jQuery all'interno di un progetto Rails.

Cosa vuol dire sostituire jQuery a Prototype?

Prototype non è semplicemente distribuito in bundle con un'applicazione Rails. Rails infatti mette a disposizione numerosi helper che si preoccupano di convertire in JavaScript il nostro codice Ruby, agevolando il compito del programmatore. Questi helper sono contenuti in diversi moduli, uno fra tutti ActionView::Helpers::PrototypeHelper.

Prendiamo ad esempio l'helper link_to_remote. Questo metodo costituisce la versione ajaxificata dell'helper link_to e consente di inserire un link che, una volta selezionato, esegue una chiamata ajax con i parametri specificati.

<!-- link alla pagina di creazione di un nuovo post -->
<%= link_to 'New post', new_post_path %>

<!-- link ajax alla pagina di creazione di un nuovo post -->
<%= link_to_remote "New post",
  :url => new_post_path,
  :update => { :success => "form", :failure => "error" }
%>

Sebbene l'uso sia molto simile, il risultato è decisamente diverso. Nel secondo caso, infatti, Rails si preoccupa di convertire in automatico il nostro codice Ruby nel codice HTML e JavaScript necessario per eseguire l'azione con Prototype, interpretare la risposta ed aggiornare la pagina corrente.

<!-- link alla pagina di creazione di un nuovo post -->
<a href="/posts/new">New post</a>

<!-- link ajax alla pagina di creazione di un nuovo post -->
<a href="#" onclick="new Ajax.Updater({success:'form',failure:'error'}, '/posts/new', {asynchronous:true, evalScripts:true, parameters:'authenticity_token=' + encodeURIComponent('cc33153cbe90fcce6ba4a0de069a2b925969721b')}); return false;">New post</a>

Poiché le API di jQuery differiscono da quelle di Prototype, per integrare con successo jQuery all'interno di un progetto Rails è necessario riscrivere gli helper per la conversione del codice Ruby in istruzioni JavaScript.

jQuery o Prototype: non entrambi!

A qualcuno potrebbe venire in mente di utilizzare jQuery includendo il file sorgente ed usandolo all'occorrenza, mantenendo in parallelo Prototype per tutte le interazioni con Rails. Esistono almeno due buoni motivi per non farlo.

  1. Prototype e jQuery non possono essere utilizzati in contemporanea su una pagina web. Entrambi i framework utilizzano alcuni nomi di metodo convenzionali, come ad esempio il comando $, entrando così in conflitto se inclusi in parallelo.
  2. Entrambi i framework comportano un certo carico di elaborazione sul computer dell'utente che, in alcuni casì, è percepibile anche con un solo framework. Includerli entrambi potrebbe causare visibili rallentamenti in fase di caricamento ed interpretazione di una pagina da parte del browser.

Come integrare jQuery con Rails

Esistono almeno due modi per integrare jQuery in un progetto Rails.

Integrazione manuale

Il primo modo consiste nell'includerlo come un normale framework JavaScript, non prima di aver rimosso ogni traccia di Prototype. Così facendo si rinuncia però a tutti i metodi per scrivere JavaScript direttamente attraverso Rails.

Scarichiamo dal sito jquery.com la versione che desideriamo utilizzare e salviamola nella cartella /public/javascripts. Poi richiamiamo il file jquery.js ed il consueto file application.js all'interno del nostro layout.

<!-- app/views/layouts/application.html.erb -->
<%= javascript_include_tag 'jquery', 'application' %>

Questa soluzione può andare bene per progetti di piccole dimensioni con limitato uso di AJAX ed effetti. Nella maggior parte dei casi, rinunciare agli helper è una scelta controproducente.

Integrazione con jRails

L'alternativa al metodo precedente consiste nel sostituire trasparentemente Prototype con jQuery mappando i vecchi metodi su quest'ultimo framework. La soluzione si chiama jRails, un plugin sviluppato appositamente con questo obiettivo. E' sufficiente installare il plugin per avere a disposizione tutti i principali helper rimappati su jQuery.

$ ruby script/plugin install http://ennerchi.googlecode.com/svn/trunk/plugins/jrails

+ ./CHANGELOG
+ ./README
+ ./init.rb
+ ./install.rb
+ ./javascripts/jquery-ui.js
+ ./javascripts/jquery.js
+ ./javascripts/jrails.js
+ ./javascripts/sources/jrails.js
+ ./lib/jrails.rb
+ ./tasks/jrails.rake
Copying files...
Files copied - Installation complete!

Una volta installato, jRails copia all'interno della cartella /public/javascrips tre file:

  1. Il file di jQuery
  2. Il file di jQuery UI
  3. Un file con alcune funzioni personalizzate utili all'integrazione

E' possibile di includere l'espansione :default contenente tutti i file o selezionare i file singolarmente.

<!-- inclusione standard del gruppo :default -->
<%= javascript_include_tag :defaults %>

<!-- automaticamente verranno inclusi i seguenti file -->
<script src="/javascripts/jquery.js" type="text/javascript"></script>
<script src="/javascripts/jquery-ui.js" type="text/javascript"></script>
<script src="/javascripts/jrails.js" type="text/javascript"></script>
<script src="/javascripts/application.js" type="text/javascript"></script>

<!-- inclusione dei singoli file -->
<%= javascript_include_tag 'jquery', 'jquery-ui', 'jrails', 'application' %>

Nel caso abbiate esigenza di usare una versione di jQuery differente da quella inclusa con il plugin, è possibile sostituire i singoli file all'interno della cartella /public/javascripts con quelli corrispondenti.

jRails è un progetto giovane che purtroppo non garantisce ancora una compatibilà al 100% con tutti i comportamenti originali previsti per Prototype. E' comunque abbastanza stabile da consentirne l'utilizzo in produttività. Tutti gli esempi seguenti faranno riferimento unicamente a questa modalità di integrazione.

Modalità mista

In alcuni casi potreste voler utilizzare le funzionalità offerte da jRails senza includere fisicamente il sorgente di jQuery all'interno della vostra applicazione. Chi si è interessato almeno una volta di performance avrà senz'altro sentito parlare dell'acronimo CDN, meglio conosciuto come Content Delivery Network.

Da qualche tempo sia Google sia Yahoo! offrono la possibilità di includere le principali librerie javascript direttamente dai loro server, con numerosi vantaggi.

  1. I browser possono riutilizzare la versione in cache della libreria anche su siti raggiungibili su domini completamente differenti.
  2. Le richieste dei file JavaScript non sono servite dai vostri server con un risparmio in termini di elaborazione e CPU.
  3. Google e Yahoo! dispongono di numerosi server in diverse collocazioni geografiche. Normalmente, quando un utente richiede un file, il file viene servito dal server più vicino alla collocazione geografica dell'utente che potrà così beneficiare di un tempo di caricamento minore.

Esistono diversi plugin che permettono di includere con pochissimo sforzo un framework JavaScript da Google o Yahoo! Il mio preferito si chiama Google Ajax Libraries. Basta installarlo ed includere la chiamata al metodo all'interno del proprio layout. Il plugin è perfettamente compatibile con jRails ed è possibile utilizzarli in contemporanea per disporre sia dell'integrazione di jQuery sia di una versione personalizzata di jQuery senza dipendere da quelle distribuite con jRails.

Utilizzare jQuery con Rails

Nel prossimo articolo vedremo un esempio pratico di come utilizzare jQuery all'interno di un progetto Rails grazie a jRails.

Stay tuned!