Abbiamo già detto che Rails di default fornisce il supporto per diversi tipi di template: i file rhtml
, i file rxml
ed i file rjs
. I file del primo tipo utilizzano semplice codice Ruby incluso nell'HTML, e sono il meccanismo più utile ed usato. I secondi sono scritti in un domain specific language costruito con Ruby per rendere semplice la realizzazione di XML generico, ed i terzi sono pensati per generare JavaScript dinamicamente, sempre tramite un piccolo DSL, per integrare meglio le tecnologie AJAX.
I file Rxml, sono molto semplici da usare ed in molti casi permettono di descrivere un albero XML in modo molto semplice. Per spiegarli però dobbiamo introdurre un concetto di Ruby che abbiamo evitato per tutta la guida, e cioè i blocchi. I blocchi sono una sorta di funzioni senza nome che vengono definite al volo e passate ad un metodo specifico, che può usarli in qualsiasi modo, ad esempio:
[1,2,3,4,5].each do |num|
print num
end
Questo codice è equivalente ad un ciclo for
, e lo stesso vale per questa altra sintassi:
12345.each { |num|
print num
}
Se guardate la documentazione di Rails troverete spesso i blocchi: i vari metodi per la costruzione di form automatici, ad esempio, in genere accettano un blocco per aggiungere elementi. Poiché questa guida non è specifica su Ruby, siete invitati ad approfondire il linguaggio se una cosa vi risulta del tutto incomprensibile.
Tornando ai template Rxml, vediamo un esempio pratico, creando un controller chiamato "feed" nel quale abbiamo intenzione di mantenere le funzionalità di gestione dei contenuti RSS o ATOM, usando ancora il solito script/generate
. Un template Rxml è fatto in questo modo:
xml.instruct! :xml, :version=>"1.0",
xml.nodo do
xml.sottonodo do
xml.contenuto("ciao")
end
end
il risultato di un codice come questo sarà una cosa del genere:
<?xml version="1.0" encoding="UTF-8"?>
<nodo>
<sottonodo>
<contenuto>ciao</contenuto>
</sottonodo>
</nodo>
La linea instruct!
(in Ruby i metodo possono avere un "!" alla fine) serve ad impostare i dati generali di un documento. Ogni chiamata ad un metodo qualunque dell'oggetto xml
creerà un nuovo nodo, se questo metodo viene chiamato con una stringa il nodo avrà come contenuto la stringa stessa, altrimenti se gli passiamo un blocco esso conterrà altri elementi. Se infine gli passiamo un Hash, esso verrà utilizzato per impostare gli attributi del tag.
Per realizzare un file RSS 2.0 servirà creare un file rss.rxml
nella cartella app/views/feed/
esattamente come se si trattasse di un altro tipo di template, ma con un codice di questo tipo:
xml << %(<?xml version="1.0"?>n)
xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/") do
xml.channel do
xml.title("HForum")
xml.link("http://html.it")
xml.description("Ultimi messaggi nel forum di html.it")
for message in Message.latest
xml.item do
xml.title(message.topic.title)
xml.description(message.body)
xml.link( url_for(:controller=>'home', :action=>'show', :id=>message.topic.id) )
end
end
end
end
Rails è in grado di capire basandosi sull'estensione che tipo di template si trova davanti, e quindi di trattarlo in modo appropriato. Se salvate questo file come rss.rhtml esso verrà considerato come un template con ruby immerso nell'HTML e quindi non funzionerà.
In questo codice ci troviamo per la prima volta di fronte ad url_for
, nell'ultima riga prima degli end
. Questo helper è pensato per costruire indirizzi, con lo stesso meccanismo che abbiamo già visto per link_to
/redirect_to
, o per le opzioni di alcuni altri helper. In effetti tutti questi metodi si appoggiano ad url_for
, quindi se avete dei dubbi relativi a come costruire un particolare url ricordate di verificare la documentazione relativa ad url_for
.
Notate che in questo codice abbiamo usato solamente due blocchi do..end
ma avremmo potuto realizzare documenti arbitrariamente complessi annidandone di più. Abbiamo anche fatto uso di un ciclo for
per generare un elemento <item></item>
per ogni messaggio, il che mostra come si possa integrare normale codice Ruby all'interno della vista senza alcuna difficoltà, con ovvi vantaggi di espressività.