Impariamo ad usare The Play Framework - IV parte
Nuovi test
In questo appuntamento vedremo come salvare nuove attività e modificare quelle già presenti nel database. Per fare questo dovremo usare il metodo save() fornito dalle API di Play e il cui scopo è di rendere persistenti le modifche ai dati; questo metodo fa parte del supporto a JPA di Play, il cui scopo è facilitare l'utilizzo di JPA (Java Persistence API); potete trovare un approfondimento sul sito stesso di Play.
Realizziamo subito un test per verificare che sia possibile salvare le attività sul database. In test/BasicTest.java aggiungiamo questo metodo:
@Test
public void test_saveActivity() {
User user = getBobUser();
Activity a = new Activity();
a.setUser(user);
a.setDate(GregorianCalendar.getInstance());
a.setLengthMinutes(30);
a.setType("Test type");
a.save();
}
Per provarlo è sufficiente far partire come al solito il server in modalità test
play test
collegarsi all'indirizzo http://localhost:9000/@tests, selezionare BasicTest.java e cliccare su "Start!". Se tutto ha funzionato correttamente il riquadro contenente BasicTest.java sarà diventato verde: buon segno!
Realizzazione
La creazione di form e la gestione di validazione e binding dei parametri è uno dei punti forti di Play. In questo appuntamento vedremo come creare un form di inserimento e modifica delle attività.
Per prima cosa aggiungiamo due action al controller Application: editActivity() e saveActivity().
public static void editActivity(Long id) {
Activity activity;
if (id != null) {
activity = Activity.findById(id);
} else {
activity = new Activity();
}
renderArgs.put("activity", activity);
render();
}
public static void saveActivity(Long id, String type, Calendar date, int lengthMinutes) {
User user = (User) renderArgs.get("user");
Activity activity;
if (id != null) {
activity = Activity.findById(id);
activity.setType(type);
activity.setDate(date);
activity.setLengthMinutes(lengthMinutes);
} else {
activity = new Activity(user, type, date, lengthMinutes);
}
Validation.required("activity.type", type);
Validation.required("activity.date", date);
Validation.required("activity.lengthMinutes", lengthMinutes);
Validation.min("activity.lengthMinutes", lengthMinutes, 1.0);
if (Validation.hasErrors()) {
renderArgs.put("activity", activity);
render("Application/editActivity.html");
}
activity.save();
index();
}
L'azione editActivity() serve per caricare la pagina di modifica:
- se viene invocata passandogli un parametro di tipo java.lang.Long, allora cercherà di caricare dal database l'attività con l'ID specificato;
- se non viene passato alcun parametro, crea un nuovo oggetto.
In questo modo è possibile utilizzare lo stesso metodo e la stessa view sia per la creazione che per la modifica.
L'azione saveActivity() si occupa invece del salvataggio vero e proprio, facendosi carico anche di validare i parametri in entrata:
Validation.required()viene usato per verificare che la property in esame sia diversa danullo vuota;Validation.min()verifica che la property in esame, di tipo numerico, abbia un valore maggiore o uguale a quello passato come argomento. Nel nostro caso verifichiamo che venga specificato, per la durata dell'attività, almeno un minuto.
Ora possiamo modificare la pagina iniziale, quella con l'elenco delle attività, aggiungendo i comandi Modifica (sulle attività esistenti) e Crea nuova (in fondo alla lista). Entrambi si riferiranno alla action Application.editActivity():
#{extends 'main.html' /}
#{set title:'Home' /}
Benvenuto su GymTrack!<br />
<small>Utente: <em>${user.fullname}</em></small>
<table>
<thead>
<tr>
<th>Data</th>
<th>Tipo di attività</th>
<th>Durata</th>
<th> </th>
</tr>
</thead>
<tbody>
#{list items:activities, as:'act'}
<tr>
<td>${act.id}</td>
<td>${act.type}</td>
<td>${act.lengthMinutes}</td>
<td>#{a @Application.editActivity(act.id)}edit#{/a}</td>
</tr>
#{/list}
</tbody>
</table>
#{a @Application.editActivity()}Crea nuova#{/a}
Il tag #{a} è utilizzato per creare un link all'azione, demandando a Play i dettagli su come ralizzare questo link. Da notare che ci si riferisce ai controller aggiungendo "@" prima del nome.
Ecco come apparirà ora la home page modificata:

Infine, abbiamo bisogno della pagina con il form di modifica, che salveremo in app/views/Application/editActivity.html:
#{extends 'main.html' /}
#{set title:'Home' /}
#{form @Application.saveActivity(id)}
#{ifErrors}
<p class="error">Correggi gli errori di compilazione</p>
#{/ifErrors}
#{if activity.id}
<input name="id" type="hidden" value="${activity.id}" />
#{/if}
Data gg/mm/aaaa
<input name="date" type="text" value="${activity.date ? activity.date.time.format('dd/MM/yyyy') : ''}" />
<span class="error">#{error 'activity.date' /}</span>
<br />
Tipo di attività
<input name="type" type="text" value="${activity.type}" />
<span class="error">#{error 'activity.type' /}</span>
<br />
Minuti
<input name="lengthMinutes" type="text" value="${activity.lengthMinutes}" />
<span class="error">#{error 'activity.lengthMinutes' /}</span>
<br />
<button type="submit">Salva</button>
#{/form}
Da notare:
- il tag
#{form}, utilizzato per creare il codice html del form, inizializzato in modo che invochi l'azione @Application.saveActivity(); - il tag #{error}, utilizzato per mostrare gli eventuali messaggi d'errore;
- l'utilizzo di property e metodi direttamente nel codice del template, ad esempio, nel campo "date":
activity.date.time.format('dd/MM/yyyy')
che è l'equivalente di
activity.getDate().getTime().format('dd/MM/yyyy')
Cliccando su una attività esistente (dalla homepage) potremmo modificarla:

Cliccando invece su Crea Nuova (sempre nella homepage) avremo un form vuoto.
Abbiamo visto che il codice del controller esegue anche una validazione dei dati inseriti; proviamo a vedere cosa succede se proviamo a creare una nuova Attività tralasciando alcuni dati o inserendoli errati, ad esempio:
- Data: inseriamo una stringa a caso, ad esempio "asdasdas";
- Tipo di attività: lasciamolo vuoto o riempito di soli spazi;
- Minuti: inseriamo il valore "-10" (negativo).
Cliccando su Salva torneremo sul form, il quale ci mostrerà gli errori di validazione accanto ai rispettivi input:

Se osserviamo attentamente il codice dell'azione saveActivity() ci accorgiamo che, se tutto è filato liscio, verrà invocato il metodo/action index(). Questo farà si che, senza artifici di vario genere o configurazioni particolari (come in altri framework dello stesso tipo) il flusso di esecuzione continuerà con la rispettiva azione (index() appunto), la quele ci riporterà sulla homepage dove vedremo la nuova attività (o quella modificata) insieme alle altre:

- Versione stampabile
- Aggiungi un commento
- 228 letture

