Quali sono i punti di contatto tra il mondo Ruby on Rails e il Web 2.0? In questo articolo si farà una panoramica su software liberamente disponibile che si inserisce in questo contesto, su Ajax e su altre tecnologie, al fine di comprendere lo stato di RoR rispetto a Web 2.0.
Introduzione
L‘affermazione del Web 2.0 e le sue implicazioni tecnologiche e sociali sono ormai note a tutti noi. MokaByte se ne sta ampiamente occupando nelle sue pagine con una serie di articoli finalizzati a descriverne caratteristiche, soluzioni e ambito di azione. In questo articolo ci occuperemo di Web 2.0 in un‘ottica esclusivamente Ruby On Rails.
Il presente articolo è suddiviso logicamente in due sezioni:
- Alcuni esempi di implementazione di soluzioni Rails con una breve premessa relativa ai principi di Ajax.
- Qualche cenno ad alcuni prodotti, liberamente disponibili, vicini al mondo Web 2.0, realizzati in Rails, che possono essere interessanti punti di riferimento in materia.
Iniziamo dalla prima sezione.
Ajax. The Rails Way
Uno degli strumenti tecnologici che ha consentito l‘affermazione del Web 2.0 è, senza dubbio, legato Ajax. La disponibilità di un front-end web, al tempo stesso accattivante ma soprattutto user-oriented, ha dato un notevole impulso all‘affermazione del “content user based site”.
Innazitutto che cosa è Ajax e a che cosa serve? Facciamo una rapida descrizione.
Asynchronous JavaScript and XML, questo il significato dell‘acronimo, è una tecnica che permette di estendere le usuali (ormai del Web 1.0) funzionalità nelle applicazioni web ricaricando frammenti della pagina HTML in maniera asincrona, consentendone aggiornamento o sostituzione senza che questa operazione coinvolga l‘intera pagina.
Figura 1. Il modello di classica applicazione web 1.0 e quello di applicazione web 2.0 [fonte Adaptive Path]
La presenza di un Ajax Engine nella versione 2.0 del Web consente una serie di operazioni al tempo stesso utili e accattivanti per l‘utente finale.
È sufficiente aprire un account su GMail per averne un‘idea precisa di quale possa essere il risultato finale dell‘operazione.
Il risultato più intrigante, derivante dall‘utilizzo di Ajax, è una navigazione web “non bloccata” da operazioni di richiesta del browser, cosa questa particolarmente sgradevole al rapido e smaliziato utente Internet.
Figura 2 – Il modello sincrono confrontato con quello asincrono [fonte Adaptive Path]
Ma fin qui abbiamo motivato solo la A di Ajax, cioè Asynchronous.
Passiamo alla Ja = JavaScript. Al fine di gestire le richieste Ajax effettuate dalla pagina web si ricorre al JavaScript e in particolare a determinate librerie che mettono a disposizione una serie di funzionalità (= funzioni) atte a raggiungere lo scopo.
In particolare noi utilizzeremo il framework Prototype per i nostri semplici esempi, una libreria che facilita la realizzazione di soluzioni dinamiche.
La X = XML nell‘acronimo è motivata più che altro da ragioni storiche poiché non è detto che i dati passati su XMLHttpRequest siano in formato XML.
Aggiungiamo che la comunicazione tra il client e il server avviene ricorrendo a XMLHttpRequest, “…una API che può essere utilizzata in JavaScript, e in altri linguaggi di scripting per trasferire XML e altri formati testo verso e dal web server utilizzando HTTP, realizzando una comunicazione su di un canale indipendente tra la pagina web lato client e la componente server.” [Wikipedia].
Ajax è chiaramente utilizzabile da qualsiasi ambiente lato server ma Rails nasce con un supporto built-in. Sviluppare applicazioni basate su RoR che ricorrono largamente ad Ajax è quindi piuttosto semplificato.
Facciamo qualche esempio in merito.
Apriamo Aptana, con il supporto RoR, e creiamo un progetto Rails di nome MokabyteAjax.
Tutti gli effetti Ajax e le operazioni DOM disponibili sono contenute nei .js presenti in public/javascript e creati in automatico alla generazione del progetto.
Per renderle disponibili all‘interno della componente view è sufficiente effettuare la seguente chiamata nella sezione
<%= javascript_include_tag("prototype", "effects") %>
Possiamo immettere questa inclusione nella pagina template in modo tale che sia immediatamente disponibile per tutte le pagine che ci fanno riferimento.
In generale per fare una invocazione Ajax si ricorre ad un espressione simile alla seguente:
<%= link_to_remote("Do something", :update => ‘myajaxdiv‘,
:url => { :action => :actionname }) %>
dove il primo parametro risulta essere il testo del link, il secondo l‘elemento (id) della pagina che sarà aggiornato e il terzo è la action che viene invocata.
Ovviamente nella view sarà presente qualcosa del tipo
Something will be changed
che rappresenta la parte di front-end che sarà “rimpiazzata” con il risultato dell‘operazione effettuata.
Facciamo un esempio molto banale che ci spieghi questa situazione.
Usando la view “generators” di Aptana creiamo un controller di nome “first” con due metodi “index” e “dothing”. Ormai sappiamo che in automatico avremo disponibili sia il controller che i file di view. Aggiungiamo in app/views/layout il file application.rhtml con il seguente contenuto
<%= javascript_include_tag "prototype", "effects" %>
Mokabyte - Rails & Web 2.0
<%= @content_for_layout %>
In tal modo abbiamo disponibili i file .js della libreria Prototype per tutti i file dell‘applicazione (a meno che non provvediamo a disabilitare l‘utilizzo del template).
Il file appviewsfirstindex.rhtml sarà la pagina all‘interno della quale è presente il “div” che sarà aggiornato
<%= link_to_remote("Do something", :update => ‘myajaxdiv‘,:url => { :action => :dothing }) %>Something will be changed
mentre il file appviewsfirstdothing.rhtml conterrà
ÃÂ ÃÂ ÃÂ Hello World from Ajax!
ÃÂ ÃÂ ÃÂ (DateTime.now = <%= DateTime.now %>)
l‘oggetto dell‘aggiornamento della pagina index.rhtml
Per far funzionare il tutto è necessario disabilitare l‘utilizzo dei template per la seconda pagina.
Aggiungiamo al metodo ‘dothing‘ del first_controller.rb il seguente codice
render(:layout => false)
A questo punto possiamo fare lo start del nostro server MokabyteAjaxServer ed invocare
http://localhost:3000/first/index.
Clicchiamo su “Do something” ed otteniamo qualcosa simile a quanto mostrato in figura 3.
Figura 3 – Risultato dell‘invocazione Ajax
Passiamo a un esempio un pò più evoluto. Si tratta di una lista di elementi che si aggiorna mediante Ajax, quindi senza ricaricare l‘intera pagina ma solo il frammento di interesse.
Introduciamo qualche elemento di interesse all‘esempio simulando la presenza di una base dati di elementi “da fare” aggiungendo nel model una classe todo.rb (appmodels odo.rb) con il seguente contenuto:
class Todo
ÃÂ attr_reader :element
ÃÂ attr_reader :postingTime
ÃÂ DATABASE = []
ÃÂ def initialize(element)
ÃÂ ÃÂ @element = element
ÃÂ ÃÂ @postingTime = Time.now
ÃÂ ÃÂ DATABASE.unshift(self)
ÃÂ end
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ
ÃÂ def self.find_recent
ÃÂ ÃÂ DATABASE
ÃÂ end
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ
ÃÂ # Todo
ÃÂ new("Buying a Rails book")
ÃÂ new("Taking a coffee")
end
Questa classe ci serve sia come contenitore sia come accessor, cioè per fornire l‘elenco dei nostri “todos” aggiornati.
Usando il generatore di codice di Rails creiamo un controller “list” con due metodi “index” e “add_element”. Li completiamo con il seguente sorgente.
class ListController
ÃÂ < ApplicationController
ÃÂ ÃÂ def add_element
ÃÂ ÃÂ ÃÂ todo = Todo.new(params[:element_body])
ÃÂ ÃÂ ÃÂ render(:partial => "todo", :object => todo,:layout => false)
ÃÂ ÃÂ ÃÂ end
ÃÂ ÃÂ def index
ÃÂ ÃÂ @todos = Todo.find_recent
ÃÂ ÃÂ end
end
Il metodo index ci serve per recuperare la lista di elementi, mentre add_element per aggiungere il nuovo elemento (il parametro consente di recuperare i dati dal front end) e poi reindirizzare al front-end per aggiungere il nuovo elemento alla lista dei già presenti.
Passiamo alla componente view. Questa è la componente che più risente dell‘impatto dovuto all‘adozione di un Ajax Engine.
Nel corso della trattazione ci imbatteremo nei template di Rails (in realtà anche nel micro esempio precedente ci siamo passati molto vicini). così facendo inizieremo ad introdurli per poi trattarli più ampiamente in articoli futuri.
Introduciamo l‘elemento principale di novità nella view Ajax, e cioè l‘istruzione form_remote_tag().
form_remote_tag(:url => { :action => "actionname" },
:update=> "div_to_update")
Questa, in luogo di form_tag() normalmente utilizzata per generare un form Rails, si occupa di serializzare gli elementi del form ed effettua l‘invio dei dati alla componente server tramite XMLHttpRequest. Ovviamente lato server non è richiesta alcuna modifica al codice per recepire i dati, rispetto ad un front end Web 1.0.
Nel nostro esempio ci spingeremo un pochino oltre implementando due Javascript callback (:loading, :complete) per il metodo form_remote_tag().
Questo il sorgente della pagina appviewslistindex.rhtml
<% content_for("page_scripts") do -%>
ÃÂ function todo_added() {
ÃÂ ÃÂ var todo = $(‘todos‘).firstChild;
ÃÂ ÃÂ new Effect.Highlight(todo);
ÃÂ ÃÂ Element.hide(‘busy‘);
ÃÂ ÃÂ $(‘form-submit-button‘).disabled = false;
ÃÂ }
ÃÂ function todo_loading() {
ÃÂ ÃÂ Element.show(‘busy‘);
ÃÂ ÃÂ $(‘form-submit-button‘).disabled = true;
ÃÂ }
<% end -%>
ÃÂ ÃÂ <%= render(:partial => ‘todo‘, :collection => @todos) %>
<%= form_remote_tag(:url => { :action => "add_element" },
ÃÂ :updateÃÂ ÃÂ => "todos",
ÃÂ ÃÂ ÃÂ :position => :top,
ÃÂ ÃÂ ÃÂ :loadingÃÂ => ‘todo_loading()‘,
ÃÂ :complete => ‘todo_added()‘);
%>
<%= text_field_tag(‘element_body‘, ‘‘, :id => ‘element-body-field‘) %>
<%= submit_tag("Add Item", :id => ‘form-submit-button‘) %>
ÃÂ Adding my item
<%= end_form_tag %>
In testa abbiamo l‘istruzione content_for(“page_scripts”) dove sono implementate le funzioni di callback che sono inserite (come vedremo) nella pagina template con l‘istruzione <%= @content_for_page_scripts %> che provvede ad invocarle.
A seguire abbiamo la parte di visualizzazione della lista e il form con text e submit.
Nella pagina appviewslist\_todo.rhtml abbiamo invece gli elementi della lista da mandare a video, qualcosa tipo:
ÃÂ
ÃÂ ÃÂ <%= todo.postingTime.strftime("%H:%M:%S") %>:
ÃÂ ÃÂ <%= todo.element %>
ÃÂ
La pagina template appviewslayoutslist.rhtml conterrà invece qualcosa del tipo:
ÃÂ
ÃÂ <%= javascript_include_tag("prototype", "effects") %>
ÃÂ
ÃÂMy To Do List
ÃÂ <%= stylesheet_link_tag ‘mokabyte‘ %>ÃÂMy List
ÃÂ <%= @content_for_layout %>
Rimandiamo a un prossimo articolo per tutti i dettagli relativi ai meccanismi della componente view ed in particolare dei template, ma la potenza dello strumento è ben evidente già da questi semplici esempi. Siamo a questo punto pronti per invocare
http://localhost:3000/list/index
e iniziare ad aggiungere elementi alla lista in modalità 2.0.
Figura 4 – La lista che si aggiorna senza ricaricare la pagina
A questo punto avremo tutti gli strumenti necessari per dare avvio alla realizzazione di una accattivante applicazione Rails Web 2.0 e per introdurre degli effetti veramente… “speciali”.
Qualche soluzione
Passiamo ora a dare un‘occhiata ad alcuni prodotti realizzati in Rails che ben si inseriscono nell‘ambito Web2.0. Perchè lo facciamo? Il fatto che questi prodotti siano tutti realizzati utilizzando lo stesso framework, il fatto che questo framework abbia regole abbastanza vincolanti (basti pensare alla struttura in cartelle, allo switch tra ambiente di sviluppo, test, produzione) unito alla disponibilità del codice sorgente rende di fatto facilmente utilizzabile non solo il prodotto ma anche solo parti di questo o rende semplificata l‘eventuale integrazione con altro software con le medesime componenti. Aggiungiamo anche che conoscere queste applicazioni ci abilita automaticamente a un‘utilizzo “as is” del software, cosa questa abbastanza frequente in caso di blog, wiki, ecc.
Iniziamo da due prodotti per la gestione di blog, Typo (http://typosphere.org/) e Mephisto (http://www.mephistoblog.com). Sono entrambi dei prodotti WordPress-like realizzati in Rails. Facilissimi da installare con MySQL (almeno utilizzando WeBrick o Mongrel), meritano sicuramente una citazione (e una prova).
Figura 5 – Il sito di Mephisto, basato su Mephisto
Figura 6 – Un‘ installazione in locale di Typo
Tra le altre cose la lista di alcuni dei blog che si poggiano su Typo (http://trac.typosphere.org/wiki/TypoPowered) è tutt‘altro che trascurabile…
Nel mese di giugno, l‘ articolo sul Web 2.0 è stato dedicato all‘argomento wiki. Si è fatto riferimento a varie implementazioni, tra cui MediaWiki (PHP) e soprattutto XWiki (Java). Anche RoR dispone di una propria implementazione wiki. Si tratta di Instiki (http://www.instiki.org). Niente di particolare dal punto di vista funzionale. Si tratta di un ennesimo wiki-clone i cui punti di forza risultano essere la facilità di installazione e di utilizzo.
Andiamo oltre e arriviamo ad Ozimodo (http://ozimodo.rubyforge.org/), un tumblelog. Che cosa è un tumblelog? Wikipedia dice che “Un tumblelog è una variante del blog, che favorisce una forma abbreviata, arricchita da multimedialità , rispetto a quelli che sono i lunghi editoriali frequentemente associati ai blog. La forma di comunicazione comunemente usata include collegamenti, fotografie, citazioni, dialoghi di chat e video. A differenza dei blog questo formato è frequentemente usato dall‘autore per condividere creazioni, scoperte, esperienze senza la necessità di commentarle”.
Figura 7 – Ozimodo al lavoro
Veramente divertente metter su un blog (o come lo vogliamo chiamare) prendendo un video da YouTube, uno da GoogleVideo, caricando tue immagini personali, postando articolo di solo testo e così via. Uno spasso. Provatelo e non ve ne pentirete.
Abbiamo citato qualche prodotto, tra quelli di cui abbiamo esperienza diretta, ma se volessimo andare alla ricerca di qualcos‘altro, sia esso Web 2.0 oppure Web “tradizionale” o applicazione standalone in Ruby possiamo dare un‘occhiata a RAA (Ruby Application Archive) (http://raa.ruby-lang.org/) e a RubyForge (http://rubyforge.org).
Repository appostamente predisposti, sono punti di riferimento da tener sempre presenti nella ricerca. Prima di dedicarsi alla realizzazione from scratch, vale sempre la pena dare un‘occhiata.
Conclusioni
Abbiamo introdotto molti nuovi elementi da approfondire in ambito Rails/Ajax/Soluzioni Web2.0.
Sicuramente Ruby e Rails risultano essere sufficientemente maturi per implementazioni di questo tipo. Prova ne sono la facilità di realizzazione e le implementazioni disponibili.
Aggiungerei anche che laddove, in contesti “non enterprise” non abbiamo necessità di solide, ma costose applicazioni Java EE, Rails fornisce una valida soluzione Ajax-based, MVC e Object Oriented.
Riferimenti
[1] Dave Thomas, “Agile Software Development with Rails. The Pragmatic Programmer‘s Guide”, Pragmatic Bookshelf, 2005
http://www.pragmaticprogrammer.com
[2] A. Brandolini, “Il punto sul Web 2.0”, Mokabyte 113, gennaio 2007
[3] S. Rossini, “Il Web 2.0 – II parte: Wiki”, Mokabyte 118, Maggio 2007
[4] S. Rossini – A. Rocca, “Il Web 2.0 – III parte: Ajax”, Mokabyte 120, Luglio/Agosto 2007
[5] Jesse James Garrett, “Ajax: A New Approach to Web Applications”, Adaptive Path
[4] Prototype – The Javascript framework
http://www.prototypejs.org/
[5] Instiki
http://www.instiki.org
[6] Ozimodo – tumbleloggin‘ on rails
http://ozimodo.rubyforge.org/
[7] Mephisto
http://mephistoblog.com/
[7] Typo
http://typosphere.org/