ActionView
ActionPack, di cui Action View è parte insieme ad Action Controller, gestisce il meccanismo che consente di processare le richieste, di generare le risposte a tali richieste e di far scambiare dati tra il controller e la view. Il modulo ActionView, come si può ben immaginare, contiene le funzionalità necessarie alla gestione della componente "vista", in particolare il "rendering" dei template, al fine di generare HTML o XML. In Rails le tipologie di template disponibili sono le seguenti:
rhtml template rxml template rjs template (Ruby JavaScript Template, di cui non ci occuperemo in questo articolo)
Iniziamo dalla prima tipologia e facciamoci aiutare da un esempio per capirne il funzionamento. Premettiamo che un programmatore Java/JSP o PHP non dovrebbe avere alcuna perplessità nella comprensione dei template rhtml. L'immissione di codice Ruby nelle pagine html con una sintassi tipo
<%=Ruby code%>
non dovrebbe lasciare sconcertato il lettore. Passiamo immediatamente a qualche prova sul campo.
Un esempio
Creiamo una applicazione Rails chiamata RubyInAzioneI. Utilizzando un database MySQL, creiamo l'istanza MOKA e aggiungiamo la tabella "employees". Questo lo script associato.
CREATE TABLE employees (
id int(11) autoincrement, firstname varchar(60) collate utf8bin NOT NULL, lastname varchar(60) collate utf8bin NOT NULL, dob date collate utf8bin NOT NULL, PRIMARY KEY (id) )
Generiamo una scaffold application basandoci su di un controller di nome AdminEmployees e un model Employee (i file generati saranno rispettivamente admin_employees.rb e employee.rb).
Per i dettagli su come effettuare questa operazione e sulle caratteristiche di una scaffold application in Rails fare riferimento a [3]. Prima di andare ad analizzare il risultato della nostra operazione, facciamo qualche premessa partendo dall'assunto che ogni qualvolta generiamo una view, stiamo creando un template. Ora ci interessa andare ad approfondire la struttura di un template, la sua localizzazione sul file system, cosa contiene e le varie features che ci consentono di mantenere una abbastanza netta separazione tra view e controller, cioè gli helpers. La configurazione di default di Rails prevede che i template siano contenuti nella cartella "app/views". A meno di esigenze particolari di condivisione dei template tra più applicazioni, questa è la localizzazione che il metodo render(), invocato nel controller, si aspetta per le componenti della view. All'interno di questa directory sono presenti
una cartella associata ad ogni controller con all'interno i file di riferimento di ogni action; una cartella layouts all'interno della quale sono presenti i template veri e propri, uno per ogni controller di default.
A questo punto, qualsiasi personalizzazione nella struttura della pagina passa per un adeguamento di quanto contenuto in "app/views/layouts", mentre un adeguamento del contenuto della singola view associata a una action particolare necessita un intervento in "app/view/[controllername]/[viewname]". Nel caso in cui volessimo avere un unico template per l'applicazione invece di uno per ogni controller è possibile aggiungere "application.rhtml in app/view/layouts" ed eliminare il template associato al controller (o solo di alcuni che non hanno bisogno di specificità grafica).
Quanto descritto lo possiamo visualizzare nella figura 1 (e soprattutto nel codice allegato, scaricabile dal menu in alto a sinistra)
1. Abbiamo admin_employees.rhtml in app/views/layouts come struttura della pagina
I file della view che consentono di visualizzare il risultato delle operazioni CRUD complete nella cartella app/views/admin_employees 3. Per fare una prova del funzionamento del template cross-controller inseriamo application.rhtml rinominando admin_employees.rhtml (magari dopo aver introdotto una piccola modifica grafica in uno dei due template). Torna tutto?
L'invocazione della componente view avviene, ovviamente, dal controller. La modalità con la quale avviene l'invocazione è la seguente:
Consultiamo file admin_controller_emplyees.rb per visualizzare una serie di esempi. ## Potremmo anche effettuare richieste del tipo
In particolare con l'ultima invocazione abbiamo la possibilità di posizionare i template ovunque sul file system (e quindi condividerli con qualsiasi altra applicazione) All'interno dei file .rhtml di cui al punto 2. abbiamo codice html unito a codice Ruby. A livello di eleganza e separazione delle componenti architetturali non risulta essere sicuramente la migliore situazione. Per cercare di ovviare, almeno in parte, a questo inconveniente ci vengono in soccorso gli helpers. Localizzati di default in app/helpers, essi consentono di separare tutte quelle operazioni riutilizabili e che risulterebbero indubbiamente poco eleganti all'interno del codice dei template.
Helpers
Apriamo il file adminemployeeshelper.rb. All'interno troviamo qualcosa del tipo
module AdminEmployeesHelper
end
Per i dettagli sull'utilizzo dei module in Ruby facciamo riferimento a [2]. In questo caso vengono utilizzati per tener "pulito" il sorgente della view da troppo codice Ruby delegandolo all'helper di riferimento. Questo facilita, e non poco, l'interazione con il designer di turno, soprattutto in fase di recepimento delle esigenze del cliente a posteriori. Facciamo un esempio e inseriamo un banale metodo nell'helper
module AdminEmployeesHelper
def title @title || "My Title" end end
Invochiamolo in una nostra componente view con la seguente sintassi
<%=title%>
Quello che abbiamo disponibile è uno strumento molto potente. Abbiamo disponibili tutti i metodi dell'helper all'interno della view evitando così inutili ripetizioni e mantenendola di conseguenza piuttosto pulita. Rails però fa qualcosina in più, e cioè sfrutta questo meccanismo per mettere a disposizione dei built-in helpers, (senza doverli implementare quindi) relativi a formattazione di date, numeri e testo, strumenti ai quali il programmatore ricorre piuttosto frequentemente. Si veda la documentazione RDoc in merito alle numerose possibilità in questo ambito (ci riferiamo alle varie numbertopercentage(:number), numbertocurrency(:number), e così via).
Altre features e... compiti a casa da svolgere
A questo punto elenchiamo brutalmente una serie di caratteristiche utili al programmatore che potrà facilmente approfondire quelle di maggiore interesse. L'idea è di mettere in luce una serie di aspetti senza doverli necessariamente trattare in maniera completa (anche perchè abbastanza banali nell'utilizzo). La trattazione risulta tutt'altro che esaustiva se la finalità è comprendere il dettaglio implementativo, ma fornisce comunque un'idea delle potenzialità del framework e di quanto sia stato pensato sul campo. In sostanza: "vediamo cosa abbiamo a disposizione, e poi il modo di usarlo correttamente... lo impareremo".
Questi che seguono sono alcuni degli aspetti che segnaliamo per suscitare l'interesse del lettore cuirioso che potrà decidere di approfondirli adeguatamente.
Form and Field Helpers
Rails dispone di una serie piuttosto ricca di helpers di supporto alla creazione delle form e degli oggetti in questi contenuti (select, text, button, ecc). La sintassi risulta essere qualcosa del genere:
<% form_tag :action => 'actionname', :id => @list do %> ... <% end %>
<%= linkto 'Link Description', :action => 'actionname' %> <%= stylesheetlink_tag 'stylesheetfile' %>
mycars = {
'utilitaria' => 'Panda', 'supercar' => 'Ferrari', 'stationwagon' => 'Volvo 240'
}
xml = Builder::XmlMarkup.new( :target => $stdout, :indent => 2 )
xml.instruct! :xml, :version => "1.1", :encoding => "US-ASCII"
xml.mycars do mycars.each do | name, choice | xml.mycars( choice, :item => name ) end end
