In questo tutorial in tre parti, ci immergeremo profondamente nella creazione di un'app per la gestione delle liste in Node.js e Geddy. Questa è la seconda parte della serie, dove creeremo una semplice app per la gestione delle liste.
Come aggiornamento veloce, l'ultima volta che abbiamo installato Node e Geddy, abbiamo generato una nuova app e abbiamo imparato come avviare il server. In questo tutorial svilupperemo ciò che abbiamo fatto l'ultima volta, quindi assicurati di aver completato quello prima di continuare.
Geddy ha un generatore di risorse integrato; questo ci consentirà di generare automaticamente un modello, un controller, viste e percorsi per una risorsa specifica. La nostra app per fare la lista avrà solo una risorsa: fare
. Per generarlo, solo CD
nella directory della tua app (cd percorso / a / tuo / todo_app
) e corri:
geddy resource todo
Ora dovresti avere questi file aggiunti alla tua app:
Il tuo config / router.js
dovrebbe anche essere aggiunto a questo:
router.resource ( 'Todos');
Se sei nuovo su MVC, tutto questo potrebbe sembrare un po 'scoraggiante per te. Non preoccuparti però, è davvero semplice una volta capito.
modelli / todo.js: Questo file è dove definiremo il nostro fare
modello. Definiremo un numero di proprietà che tutto fare
'farsi la barba. Scriveremo anche alcune convalide dei dati qui.
controllori / todos.js: Questo file è dove tutto il / Todos /
i percorsi finiscono. Ogni azione in questo controller ha una rotta corrispondente:
GET / todos / => indice POST / todos / => crea GET / todos /: id => mostra PUT / todos /: id => Aggiorna DELETE / todos /: id => rimuovi GET / todos /: id / add = > aggiungi GET / todos /: id / edit => modifica
views / Todos /: Ogni file qui corrisponde a uno dei OTTENERE
percorsi che ti abbiamo mostrato sopra. Questi sono i modelli che usiamo per generare il front-end dell'app. Geddy usa EJS (JavaScript incorporato) come linguaggio dei modelli. Dovrebbe sembrare familiare se tu abbia mai usato PHP o ERB. In pratica, puoi utilizzare qualsiasi JavaScript che desideri nei tuoi modelli.
Ora che abbiamo generato un sacco di codice, verifica che abbiamo tutti i percorsi di cui abbiamo bisogno. Avvia di nuovo l'app (Geddy
) e indirizzare il browser a http: // localhost: 4000 / todos. Dovresti vedere qualcosa di simile
Vai avanti e prova quello per l'altro OTTENERE
percorsi anche:
Tutto bene? Bene, continuiamo.
In Geddy (e nella maggior parte degli altri framework MVC), utilizzi i modelli per definire il tipo di dati con cui la tua app funzionerà. Abbiamo appena generato un modello per il nostro fare
s, quindi vediamo cosa ci ha dato:
var Todo = function () // Qualche commento commentato; // Qualche altro codice commentato Todo = geddy.model.register ('Todo', Todo);
I modelli sono piuttosto semplici in Geddy. Stiamo solo creando una nuova funzione di costruzione per il nostro fare
s e registrandolo come modella in geddy. Definiamo alcune proprietà per il nostro fare
S. Elimina tutto il codice commentato e aggiungilo alla funzione contructor:
var Todo = function () this.defineProperties (title: type: 'string', richiesto: true, id: tipo: 'stringa', richiesto: true, stato: tipo: 'stringa', obbligatorio : vero ); ;
Nostro fare
s avrà un titolo, un id e uno status, e tutti e tre saranno richiesti. Ora impostiamo alcune convalide per il nostro fare
S.
var Todo = function () this.defineProperties (title: type: 'string', richiesto: true, id: tipo: 'stringa', richiesto: true, stato: tipo: 'stringa', obbligatorio : vero ); this.validatesPresent ( 'title'); this.validatesLength ('title', min: 5); this.validatesWithFunction ('status', function (status) return status == 'open' || status == 'done';); ;
Stiamo verificando che il titolo sia presente, che il titolo abbia una lunghezza minima di 5 caratteri e che stiamo utilizzando una funzione per verificare che lo stato sia Aperto
o fatto
. Ci sono alcune funzioni di valenza che sono integrate, vai avanti e controlla il progetto su http://github.com/mde/geddy per saperne di più su di loro.
Ora che abbiamo impostato il nostro modello, possiamo creare un punto in cui memorizzare i nostri modelli. Ai fini di questo tutorial, terremo i dati in memoria. Metteremo una serie di todos fuori dal nostro globale Geddy
oggetto in cui inserire i dati. Nella parte successiva di questa serie, inizieremo a conservarli in un database.
Apri il tuo config / Init.js
file. Tutto ciò che dovrebbe essere lì ora è un gestore globale di eccezioni non rilevate:
// Aggiungi il gestore di eccezioni non rilevate negli ambienti prod-if se (geddy.config.environment! = 'Sviluppo') process.addListener ('uncaughtException', function (err) geddy.log.error (JSON.stringify (err )););
Subito dopo quel blocco di codice, appendiamo il nostro array al Geddy
globale:
geddy.todos = [];
Lì, ora abbiamo un posto dove riporre il nostro fare
S. Ricorda, questo è nella memoria dell'applicazione, quindi scomparirà quando riavvierai il server.
Un adattatore modello fornisce la base salvare
, rimuovere
, caricare
, e tutti
metodi di cui un modello ha bisogno. La nostra fonte di dati è piuttosto semplice (solo un array!), Quindi scrivere il nostro adattatore modello dovrebbe essere abbastanza semplice.
Crea una directory in lib
chiamato model_adapters
e creare un file in lib / model_adapters
chiamato todo.js
. Apriamo il file e aggiungiamo qualche codice di codice:
var Todo = new (function () ) (); exports.Todo = Todo;
Tutto quello che stiamo facendo qui è la creazione di un nuovo oggetto vuoto da esportare in qualunque cosa richieda questo file. Se desideri sapere qualcosa in più su come funziona il metodo Node, questo articolo ha una buona panoramica. In questo caso, il nostro Init.js
il file farà il necessario.
Quindi abbiamo creato un nuovo oggetto adattatore Todo. Al momento è piuttosto sterile, ma ci arriveremo presto. Per ora, dovremo tornare a init.js e aggiungere del codice in modo che venga caricato nella nostra app all'avvio. Dopo il geddy.todos = [];
nel config / Init.js
aggiungi queste due linee:
geddy.model.adapter = ; geddy.model.adapter.Todo = require (process.cwd () + '/lib/model_adapters/todo').Todo;
Abbiamo creato un oggetto model-adapter vuoto e aggiunto l'adattatore del modello Todo su di esso.
Ora che abbiamo installato il nostro modello e il nostro adattatore, possiamo iniziare con la logica dell'app. Iniziamo con l'aggiunta di elementi da fare nella nostra lista delle cose da fare.
Quando si lavora con i dati, il primo posto che si dovrebbe andare è l'adattatore del modello. Dobbiamo essere in grado di salvare un'istanza del nostro modello Todo nel nostro array geddy.todos. Quindi apriti lib / model_adapters / todo.js
e aggiungi un metodo di salvataggio:
var Todo = new (function () this.save = function (todo, opts, callback) if (typeof callback! = 'function') callback = function () ; todo.saved = true; geddy. todos.push (todo); return callback (null, todo);) ();
Tutto ciò che dobbiamo fare è impostare la proprietà salvata dell'istanza su true e inserire l'elemento nell'array geddy.todos. In Node, è meglio fare tutto l'I / O in modo non bloccante, quindi è una buona idea prendere l'abitudine di usare i callback per passare i dati. Per questo tutorial non ha importanza, ma più avanti quando iniziamo a persistere, sarà utile. Noterai che ci siamo assicurati che il callback sia una funzione. Se non lo facciamo e usiamo save senza callback, avremo un errore. Ora passiamo al controller per creare un'azione.
Vai avanti e dai un'occhiata al creare
azione in app / controller / todos.js
:
this.create = function (req, resp, params) // Salva la risorsa, quindi visualizza la pagina index this.redirect (controller: this.name); ;
Abbastanza semplice, vero? Geddy l'ha soppressa per te. Quindi modifichiamolo un po ':
this.create = function (req, resp, params) var self = this, todo = geddy.model.Todo.create (title: params.title, id: geddy.string.uuid (10), stato: 'aperto '); todo.save (function (err, data) if (err) params.errors = err; self.transfer ('add'); else self.redirect (controller: self.name);) ; ;
Innanzitutto, creiamo una nuova istanza del modello Todo con geddy.model.Todo.create
, passando il titolo che il nostro modulo ci invierà e impostando i valori predefiniti per l'ID e lo stato.
Quindi chiamiamo il metodo di salvataggio che abbiamo creato sull'adattatore del modello e reindirizziamo l'utente sulla rotta / todos. Se non ha superato la convalida, o riceviamo un errore, usiamo il controller trasferimento
metodo per trasferire la richiesta nuovamente al Inserisci
azione.
Ora è il momento per noi di impostare il modello di aggiunta. Dare un'occhiata al app / views / todos / add.html.ejs
, Dovrebbe sembrare come questo:
Parametri
<% for (var p in params) %>
- <%= p + ': ' + params[p]; %>
<% %>
Non ne avremo bisogno
per il nostro caso d'uso, quindi sbarazziamoci di esso per ora. Rendere il vostro add.html.ejs
Assomiglia a questo:
<%= partial('_form', params: params); %>
Parziali ti offrono un modo semplice per condividere il codice tra i tuoi modelli.
Noterai che stiamo usando un partial in questo template. Parziali ti offrono un modo semplice per condividere il codice tra i tuoi modelli. I nostri modelli di aggiunta e modifica useranno entrambi la stessa forma, quindi ora creiamo questo modulo in modo parziale. Crea un nuovo file nel views / Todos /
directory chiamata _form.html.ejs
. Usiamo un trattino basso per capire facilmente se questo modello è parziale. Aprilo e aggiungi questo codice:
<% var isUpdate = params.action == 'edit' , formTitle = isUpdate ? 'Update this To Do Item' : 'Create a new To Do Item' , action = isUpdate ? '/todos/' + todo.id + '?_method=PUT' : '/todos' , deleteAction = isUpdate ? '/todos/' + todo.id + '?_method=DELETE' :", btnText = isUpdate ? 'Update' : 'Add' , doneStatus = isUpdate ? 'checked' :", titleValue = isUpdate ? todo.title :", errors = params.errors; %>
Whoa, questo è un sacco di codice lì! Vediamo se possiamo attraversarlo. Dal momento che due template differenti useranno questo partial, dobbiamo assicurarci che il form abbia un aspetto giusto in entrambi. La maggior parte di questo codice è in realtà un file standard da Bootstrap di Twitter. È ciò che permette a questa app di apparire così buona da subito (e anche sui dispositivi mobili!).
Per rendere questa app ancora più bella, puoi utilizzare il file CSS fornito nel download dell'app demo.
La prima cosa che abbiamo fatto è stata impostare alcune variabili da utilizzare. Nel Inserisci
azione che stiamo passando a params
oggetto fino al modello nel rispondere
chiamata al metodo. Questo ci dà alcune cose - ci dice quale controller e azione è stata indirizzata a questa richiesta, e ci fornisce tutti i parametri di query che sono stati passati nella url. Abbiamo istituito il isUpdate
variabile per vedere se siamo attualmente sull'azione di aggiornamento, e quindi impostiamo alcune altre variabili per aiutare a ripulire il nostro codice di visualizzazione.
Da lì, tutto ciò che abbiamo fatto è stato creare un modulo. Se siamo sull'azione di aggiunta, eseguiamo semplicemente il rendering del modulo così com'è. Se siamo nell'azione di modifica, compiliamo il modulo per consentire all'utente di aggiornare i campi.
Si noti che il modulo invierà a INVIARE
richiesta al / Todos /
con un _method = PUT
parametro. Geddy usa il metodo standard per sostituire i parametri per consentire l'invio METTERE
e ELIMINA
richiede dal browser senza dover utilizzare JavaScript. (almeno nella parte frontale!)
L'ultimo piccolo dettaglio che dobbiamo dare un'occhiata è il pulsante "Rimuovi". Stiamo usando html5 FormAction
attributo per cambiare l'azione per questo modulo. Noterai che questo pulsante FormAction
manda un INVIARE
richiesta fino al / Todos /: id
percorso con a _method = CANCELLA
parametro. Questo colpirà il rimuovere
azione sul controller, che otterremo in seguito.
Riavvia il tuo server (Geddy
) e visita http: // localhost: 4000 / todos / add per vedere il tuo modello in azione. Crea un oggetto To Do mentre ci sei.
Ora che abbiamo inserito gli elementi di input da fare dell'utente nel nostro array geddy.todos, dovremmo probabilmente elencarli da qualche parte. Iniziamo dal tutti
metodo nell'adattatore del modello.
Apriamo lib / model_adapters / todo.js
ancora e aggiungi un tutto il metodo giusto sopra il
salva 'metodo:
this.all = function (callback) callback (null, geddy.todos);
Questo è probabilmente il più semplice metodo di adattamento del modello che creeremo oggi, tutto ciò che fa è accettare un callback e chiamarlo con un errore (che è sempre nullo per ora, aggiorneremo questo metodo nel prossimo tutorial), e geddy.todos
.
Aprire /app/controllers/todos.js
di nuovo e dare un'occhiata al indice
azione. Dovrebbe assomigliare a qualcosa di simile a questo:
this.index = function (req, resp, params) this.respond (params: params); ;
Questa parte è molto semplice, usiamo solo il tutti
metodo che abbiamo appena definito sul modello-adattatore per ottenere tutto il fare
s e renderli:
this.index = function (req, resp, params) var self = this; geddy.model.adapter.Todo.all (function (err, todos) self.respond (params: params, todos: todos);); ;
Questo è tutto per il controller, ora sulla vista.
Dai uno sguardo a /app/views/todos/index.html.ejs, dovrebbe assomigliare a questo:
Parametri
<% for (var p in params) %>
- <%= p + ': ' + params[p]; %>
<% %>
Sembra molto simile al modello add.html.ejs, non è così. Ancora una volta, non avremo bisogno del parametro paramplan qui, quindi prendilo e rendi il tuo modello index.html.ejs simile a questo:
<% if (todos && todos.length) %> <% for (var i in todos) %>Lista di cose da fare
Crea una nuova attività<% %> <% %>/ Modifica "><%= todos[i].title; %>
<%= todos[i].status; %>
Anche questo è piuttosto semplice, ma questa volta abbiamo un ciclo nel nostro modello. Nell'intestazione abbiamo aggiunto un pulsante per aggiungere nuovi dettagli. All'interno del ciclo stiamo generando una riga per ciascuno fare
, mostrandone il titolo (come link ad esso modificare
pagina), ed è lo stato.
Per verificarlo, vai su http: // localhost: 4000 / todos.
Ora che abbiamo un link al modificare
pagina, dovremmo probabilmente farlo funzionare!
Apri di nuovo l'adattatore del modello (/lib/model_adapters/todo.js
). Aggiungeremo a caricare
metodo in modo che possiamo caricare uno specifico fare
e usarlo nella nostra pagina di modifica. Non importa dove lo aggiungi, ma per ora mettiamolo tra il tutti
metodo e il salvare
metodo:
this.load = function (id, callback) for (var i in geddy.todos) if (geddy.todos [i] .id == id) return callback (null, geddy.todos [i]); callback (message: "To Do not found", null); ;
Questo metodo di caricamento richiede un ID e un callback. Passa attraverso gli elementi in geddy.todos
e controlla se l'elemento corrente è id
corrisponde al passato id
. Se lo fa, chiama il callback, passando il fare
oggetto indietro. Se non trova una corrispondenza, chiama la richiamata con un errore. Ora dobbiamo usare questo metodo nell'azione show del controller di todos.
Apri il tuo Todos
controller di nuovo e dare un'occhiata è modificare
azione. Dovrebbe assomigliare a qualcosa di simile a questo:
this.edit = function (req, resp, params) this.respond (params: params); ;
Usiamo il metodo di caricamento che abbiamo appena creato:
this.edit = function (req, resp, params) var self = this; geddy.model.Todo.load (params.id, function (err, todo) self.respond (params: params, todo: todo);); ;
Tutto quello che stiamo facendo qui è caricare il todo e inviarlo al modello da renderizzare. Quindi diamo un'occhiata al modello.
Aprire /app/views/todos/edit.html.ejs
. Ancora una volta non avremo bisogno del parametro paramsplan, quindi rimuoviamolo. Rendere il vostro edit.html.ejs
Assomiglia a questo:
<%= partial('_form', params: params, todo: todo); %>
Questo dovrebbe sembrare molto simile al add.html.ejs
file che abbiamo appena modificato. Noterai che stiamo inviando un fare
oggetto fino al parziale così come i parametri questa volta. La cosa interessante è che, poiché abbiamo già scritto il partial, questo è tutto ciò che dovremo fare per far sì che la pagina di edit venga visualizzata correttamente.
Riavvia il server, creane uno nuovo fare
e fai clic sul link per vedere come funziona. Ora facciamo funzionare il pulsante di aggiornamento!
Aprire nuovamente l'adattatore del modello e trovare il salvare
metodo. aggiungeremo un po 'in modo che possiamo salvare su esistenti fare
S. Assomigli a questo:
this.save = function (todo, opts, callback) if (typeof callback! = 'function') callback = function () ; var todoErrors = null; per (var i in geddy.todos) // se è già lì, salvalo se (geddy.todos [i] .id == todo.id) geddy.todos [i] = todo; todoErrors = geddy.model.Todo.create (todo) .errors; return callback (todoErrors, todo); todo.saved = true; geddy.todos.push (todo); return callback (null, todo);
Questo loop su tutto il todo è dentro geddy.todos
e se il id
è già lì, lo sostituisce fare
con il nuovo fare
esempio. Stiamo facendo alcune cose qui per assicurarci che le nostre convalide funzionino su aggiornamenti e creazioni - per fare questo dobbiamo tirare errori
proprietà fuori da una nuova istanza del modello e passarla nuovamente nella richiamata. Se ha superato le convalide, sarà solo indefinito e il nostro codice lo ignorerà. Se non è passato, todoErrors
sarà una matrice di errori di convalida.
Ora che abbiamo questo, lavoriamo sul nostro controller aggiornare
azione.
Vai avanti e riapri il controller e trova l'azione "aggiorna", dovrebbe assomigliare a questo:
this.update = function (req, resp, params) // Salva la risorsa, quindi visualizza la pagina item this.redirect (controller: this.name, id: params.id); ;
Dovrai modificarlo per farlo apparire come questo:
this.update = function (req, resp, params) var self = this; geddy.model.adapter.Todo.load (params.id, function (err, todo) todo.status = params.status; todo.title = params.title; todo.save (function (err, data) if ( err) params.errors = err; self.transfer ('edit'); else self.redirect (controller: self.name););); ;
Quello che stiamo facendo qui sta caricando il richiesto fare
, modificarne alcune proprietà e salvarle fare
ancora. Il codice che abbiamo appena scritto nel model-adapter dovrebbe gestire il resto. Se otteniamo un errore, significa che le nuove proprietà non hanno superato la convalida, quindi trasferiremo la richiesta al modificare
azione. Se non avessimo ricevuto un errore, reindirizzeremo la richiesta nuovamente al indice
azione.
Vai avanti e provalo. Riavvia il server, creane uno nuovo fare
, clicca sul suo link di modifica, cambia lo stato in fatto
, e vedere che viene aggiornato nel indice
. Se si desidera verificare il funzionamento delle convalide, provare a modificare il file titolo
a qualcosa di più breve di 5 caratteri.
Ora otteniamo che il pulsante "Rimuovi" funzioni.
Ormai abbiamo un programma di lavoro da fare, ma se inizi a utilizzarlo per un po ', sarà difficile trovare il fare
oggetto che stai cercando su quella pagina indice. Facciamo in modo che il pulsante "Rimuovi" funzioni così che possiamo mantenere la nostra lista piacevole e breve.
Apriamo nuovamente il nostro adattatore per modello, questa volta vorremmo aggiungere un rimuovere
metodo in là. Aggiungilo subito dopo salvare
metodo:
this.remove = function (id, callback) if (typeof callback! = 'function') callback = function () ; for (var i in geddy.todos) if (geddy.todos [i] .id == id) geddy.todos.splice (i, 1); return callback (null); return callback (message: "To Do not found");
Questo è piuttosto semplice, dovrebbe somigliare molto al metodo di caricamento. Attraversa tutto il fare
s in geddy.todos
trovare il id
che stiamo cercando. Quindi giunge a quel punto dall'array e chiama il callback. Se non lo trova nella matrice, chiama la richiamata con un errore.
Usiamo questo nel nostro controller ora.
Apri di nuovo il controller e tocca il rimuovere
azione. Dovrebbe assomigliare a qualcosa di simile a questo:
this.remove = function (req, resp, params) this.respond (params: params); ;
Modificalo per farlo apparire come questo:
this.remove = function (req, resp, params) var self = this; geddy.model.adapter.Todo.remove (params.id, function (err) if (err) params.errors = err; self.transfer ('edit'); else self.redirect (controller: self .nome); );
Noi passiamo il id
che abbiamo ottenuto dai params nel modulo post in rimuovere
metodo che abbiamo appena creato. Se riceviamo un errore, reindirizziamo a modificare
azione (stiamo assumendo che il modulo abbia postato le informazioni sbagliate). Se non abbiamo riscontrato un errore, invia la richiesta al indice
azione.
Questo è tutto! Sono stati fatti.
È possibile testare la funzionalità di rimozione riavviando il server, creando un nuovo fare
elemento, facendo clic sul suo collegamento, quindi facendo clic sul pulsante "Rimuovi". Se hai fatto bene, dovresti tornare sulla pagina indice con quell'elemento rimosso.
Nel prossimo tutorial useremo il fantastico modulo mongodb-wrapper di http: //i.tv per persistere fare
in MongoDB. Con Geddy, sarà facile; tutto quello che dovremo cambiare è l'adattatore del modello.
Se avete domande, si prega di lasciare un commento qui o aprire un problema su github.