I denne tre del-opplæringen vil vi dykke dypt inn i å lage en listeliste i Node.js og Geddy. Dette er den andre delen i serien, der vi skal lage en enkel å gjøre listeadministrasjonsapp.
Som en rask oppdatering, sist gang vi installerte Node og Geddy, genererte vi en ny app, og lærte å starte serveren. I denne opplæringen bygger vi videre på hva vi gjorde sist, så sørg for at du har fullført den før du fortsetter.
Geddy har en innebygd ressursgenerator; Dette vil tillate oss å automatisk generere en modell, kontroller, visninger og ruter for en bestemt ressurs. Vår liste med apper vil bare ha en ressurs: å gjøre
. For å generere det, bare cd
i appens katalog (CD-sti / til / din / todo_app
) og kjøre:
geddy ressurs todo
Du bør nå ha disse filene lagt til i appen din:
Din config / router.js
bør også ha dette vedlagt det:
router.resource ( 'todos');
Hvis du er ny på MVC, kan alt dette virke litt skremmende for deg. Ikke bekymre deg skjønt, det er veldig enkelt når du finner ut det.
modeller / todo.js: Denne filen er der vi skal definere vår å gjøre
modell. Vi definerer et antall egenskaper som alle å gjøre
'barbere. Vi vil også skrive noen data valideringer her.
Styringer / todos.js: Denne filen er hvor alle / todos /
ruter ender opp. Hver handling i denne kontrolleren har en tilsvarende rute:
GET / todos / => index POST / todos / => opprett GET / todos /: id => vis PUT / todos /: id => oppdater DELETE / todos /: id => fjern GET / todos /: id / add = > legg til GET / todos /: id / edit => edit
visninger / todos /: Hver fil her samsvarer med en av FÅ
ruter som vi viste deg over. Dette er malene vi bruker til å generere den forreste delen av appen. Geddy bruker EJS (innebygd JavaScript) som det er templerende språk. Det bør se kjent om du noen gang har brukt PHP eller ERB. I utgangspunktet kan du bruke hvilket som helst JavaScript du vil ha i maler.
Nå som vi har generert en haug med kode, la oss bekrefte at vi har alle ruter vi trenger. Start appen på nytt (Geddy
), og pek nettleseren din til http: // localhost: 4000 / todos. Du bør se noe sånt
Gå videre og prøv det for det andre FÅ
ruter også:
Helt fint? OK, la oss fortsette.
I Geddy (og de fleste andre MVC-rammebetingelser) bruker du modeller for å definere typen data som appen din skal jobbe med. Vi har nettopp generert en modell for vår å gjøre
s, så la oss se hva som ga oss:
var Todo = funksjon () // Noen kommenterte kode; // Noen flere kommenterte kode Todo = geddy.model.register ('Todo', Todo);
Modeller er ganske enkle i Geddy. Vi lager bare en ny konstruktørfunksjon for våre å gjøre
s og registrerer det som en modell i geddy. La oss definere noen egenskaper for vår å gjøre
s. Slett all kommentert kode og legg til dette i contructor-funksjonen:
var Todo = funksjon () this.defineProperties (title: type: 'string', obligatorisk: true, id: type: 'string', obligatorisk: true, status: type: 'string' : sant); ;
Våre å gjøre
s vil ha en tittel, et id og en status, og alle tre vil være påkrevd. La oss nå angi noen valideringer for vår å gjøre
s.
var Todo = funksjon () this.defineProperties (title: type: 'string', obligatorisk: true, id: type: 'string', obligatorisk: true, status: type: 'string' : sant); this.validatesPresent ( 'tittel'); this.validatesLength ('title', min: 5); this.validatesWithFunction ('status', funksjon (status) return status == 'open' || status == 'ferdig';); ;
Vi bekrefter at tittelen er til stede, at tittelen har en minimumslengde på 5 tegn, og vi bruker en funksjon for å validere at statusen enten er åpen
eller ferdig
. Det er ganske mange validering funksjoner som er innebygd, gå videre og se prosjektet ut på http://github.com/mde/deddy for å lære mer om dem.
Nå som vi har satt opp vår todo-modell, kan vi lage et sted å lagre våre modeller. I forbindelse med denne opplæringen skal vi bare lagre dataene i minnet. Vi vil henge en todos array av vår globale Geddy
protestere mot å lagre dataene i. I neste del av denne serien begynner vi å få disse vedvarende i en database.
Åpne opp din config / init.js
fil. Alt som skal være der nå, er en global uncaught unntakshåndterer:
// Legg til uncaught-exception handler i prod-lignende omgivelser hvis (geddy.config.environment! = 'Development') process.addListener ('uncaughtException', funksjon (err) geddy.log.error (JSON.stringify )););
Like etter den koden, la oss henge vårt array av Geddy
global:
geddy.todos = [];
Der, nå har vi et sted å lagre vår å gjøre
s. Husk at dette er i programminnet ditt, så det vil forsvinne når du starter serveren på nytt.
En modelladapter gir grunnleggende lagre
, fjerne
, laste
, og alle
metoder en modell trenger. Vår datakilde er ganske enkel (bare en matrise!), Så å skrive modelladapteren vår skal være ganske enkel også.
Opprett en katalog i lib
kalt model_adapters
og lag en fil i lib / model_adapters
kalt todo.js
. La oss åpne den filen og legge til noen kjedekode:
var Todo = nytt (funksjon () ) (); eksports.Todo = Todo;
Alt vi gjør her er å sette opp et nytt, tomt objekt som skal eksporteres til hva som helst som krever denne filen. Hvis du vil vite litt mer om hvordan Node's krever metode, har denne artikkelen en ganske god oversikt. I dette tilfellet, vår init.js
filen vil gjøre det som kreves.
Så vi satte opp et nytt Todo modell-adapter objekt. Det er ganske ukjent akkurat nå, men vi kommer snart til det. For nå må vi gå tilbake til init.js og legge til noen koden slik at den er lastet inn i vår app når den starter. Etter geddy.todos = [];
i config / init.js
legg til disse to linjene:
geddy.model.adapter = ; geddy.model.adapter.Todo = kreve (process.cwd () + '/lib/model_adapters/todo').Todo;
Vi opprettet et tomt modell-adapterobjekt, og la Todo-modelladapteren på den.
Nå som vi har vår modell og modelladapter på plass, kan vi begynne på applogikken. La oss begynne med å legge til å gjøre elementer til vår å gjøre listen.
Når du jobber med data, bør du først gå til modelladapteren. Vi må kunne lagre en forekomst av vår Todo-modell til vårt geddy.todos array. Så åpne opp lib / model_adapters / todo.js
og legg til i en lagringsmetode:
var Todo = ny (funksjon () this.save = funksjon (todo, ops, tilbakeringing) hvis (type tilbakering! = 'funksjon') callback = function () ; todo.saved = true; geddy. todos.push (todo), returnere tilbakeringing (null, todo);) ();
Alt vi trenger å gjøre er å sette forekomstens lagrede eiendom til sann og skyv elementet inn i geddy.todos-arrayet. I Node er det best å gjøre alt jeg / O på en ikke-blokkerende måte, så det er en god ide å bli vant til å bruke tilbakeringinger for å overføre data rundt. For denne opplæringen spiller det ingen rolle så mye, men senere når vi starter vedvarende ting, vil det komme til nytte. Du vil merke at vi sørget for at tilbakeringingen er en funksjon. Hvis vi ikke gjør det og bruker lagre uten tilbakeringing, vil vi få en feil. La oss nå gå videre til kontrolleren, skape tiltak.
Gå videre og ta en titt på skape
handling i app / kontrollere / todos.js
:
this.create = funksjon (req, resp, params) // Lagre ressursen, og vis indeks siden this.redirect (controller: this.name); ;
Ganske enkelt, ikke sant? Geddy har stubbet det ut for deg. Så la oss endre det litt:
this.create = funksjon (req, resp, params) var selv = dette, todo = geddy.model.Todo.create (tittel: params.title, id: geddy.string.uuid (10), status: 'open '); todo.save (funksjon (feil, data) hvis (err) params.errors = err; self.transfer ('add'); annet self.redirect (controller: self.name);) ; ;
Først oppretter vi en ny forekomst av Todo-modellen med geddy.model.Todo.create
, passerer i tittelen som vårt skjema vil legge opp til oss, og sette opp standardene for id og status.
Da kaller vi lagringsmetoden som vi opprettet på modelladapteren og omdirigerer brukeren tilbake til / todos-ruten. Hvis det ikke bestod validering, eller vi får en feil, bruker vi kontrolleren overføre
metode for å overføre forespørselen tilbake til Legg til
handling.
Nå er det på tide for oss å sette opp tilleggsmalen. Se på app / visninger / todos / add.html.ejs
, det skal se slik ut:
params
<% for (var p in params) %>
- <%= p + ': ' + params[p]; %>
<% %>
Vi trenger ikke det
for vår bruk saken, så la oss bli kvitt det for nå. Lag din add.html.ejs
se slik ut:
<%= partial('_form', params: params); %>
Deler gir deg en enkel måte å dele koden mellom malene dine på.
Du vil legge merke til at vi bruker en delvis i denne malen. Deler gir deg en enkel måte å dele koden mellom malene dine på. Våre legg til og redigere maler skal begge bruke samme skjema, så la oss lage dette skjemaet delvis nå. Opprett en ny fil i visninger / todos /
katalog kalt _form.html.ejs
. Vi bruker en understrek for å enkelt fortelle om denne malen er delvis. Åpne den og legg til i denne koden:
<% 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, det er mye kode der! La oss se om vi kan gå gjennom det. Siden to forskjellige maler skal bruke denne delen, må vi sørge for at skjemaet ser riktig ut i begge deler. Mesteparten av denne koden er faktisk boilerplate fra Twitter Bootstrap. Det er det som gjør det mulig for denne appen å se så bra ut av bat (og på mobile enheter også!).
For å få denne appen til å se enda bedre, kan du bruke CSS-filen som ble levert i demo-appnedlasting.
Det første vi gjorde var satt opp noen variabler for oss å bruke. I Legg til
handling vi passerer en params
objekt ned til malen i svar
metodeanrop. Dette gir oss noen ting - det forteller oss hvilken kontroller og handling denne forespørselen er blitt henvist til, og gir oss noen spørringsparametere som ble sendt i webadressen. Vi satte opp isUpdate
variabel for å se om vi for øyeblikket er på oppdateringshandlingen, og så setter vi opp noen få flere variabler for å hjelpe oss med å rydde opp visningskoden vår.
Derfra var alt vi gjorde lage et skjema. Hvis vi er i tilleggsaksjonen, gir vi bare skjemaet som det er. Hvis vi er i redigeringsaksjonen, fyller vi ut skjemaet for å la brukeren oppdatere feltene.
Legg merke til at skjemaet vil sende en POST
forespørsel til / todos /
med en _method = PUT
parameter. Geddy bruker standardmetoden overstyr parameter for å tillate deg å sende SETTE
og SLETT
forespørsler fra nettleseren uten å måtte bruke JavaScript. (på forsiden minst!)
Den siste lille detaljene vi trenger å ta en titt på, er at "Fjern" -knappen. Vi bruker html5's formaction
Tilordne for å endre handlingen for dette skjemaet. Du merker at denne knappen er formaction
sender en POST
forespørsel opp til / Todos /: id
rute med a _method = DELETE
parameter. Dette vil treffe fjerne
handling på kontrolleren, som vi kommer til senere.
Start serveren på nytt (Geddy
) og besøk http: // localhost: 4000 / todos / legg til for å se malen din i handling. Opprett en å gjøre element mens du er på den.
Nå som vi har brukerinngang Hvis du vil legge til elementer i vårt geddy.todos-utvalg, bør vi sannsynligvis oppgi dem et sted. La oss begynne på alle
metode i modelladapteren.
La oss åpne lib / model_adapters / todo.js
igjen og legg til en all metode rett over
lagre metode:
this.all = funksjon (tilbakeringing) tilbakeringing (null, geddy.todos);
Dette er trolig den enkleste modelladaptermetoden som vi skal opprette i dag, alt som gjør det, er å godta tilbakeringing og kalle det med en feil (som alltid er null for nå, oppgraderer vi denne metoden i neste opplæring), og geddy.todos
.
Åpne opp /app/controllers/todos.js
igjen og ta en titt på index
handling. Det skal se slik ut:
this.index = funksjon (req, resp, params) this.respond (params: params); ;
Denne delen er veldig enkel, vi bruker bare alle
metode som vi nettopp har definert på modelladapteren for å få alle å gjøre
s og gjengi dem:
this.index = funksjon (req, resp, params) var selv = dette; geddy.model.adapter.Todo.all (funksjon (feil, todos) self.respond (params: params, todos: todos);); ;
Det er det for kontrolleren, nå på visningen.
Ta en titt på /app/views/todos/index.html.ejs, det skal se slik ut:
params
<% for (var p in params) %>
- <%= p + ': ' + params[p]; %>
<% %>
Ser mye ut som add.html.ejs-malen gjør det ikke. Igjen, vi trenger ikke params boilerplate her, så ta det ut, og gjør index.html.ejs mal slik:
<% if (todos && todos.length) %> <% for (var i in todos) %>Gjøremålsliste
Opprett en ny å gjøre<% %> <% %>/ Redigere "><%= todos[i].title; %>
<%= todos[i].status; %>
Denne er også ganske enkel, men denne gangen har vi en loop i vår mal. I overskriften der har vi lagt til en knapp for å legge til nye todo s. Inne i løkken genererer vi en rad for hver å gjøre
, viser den tittelen (som en lenke til den er redigere
side), og det er status.
For å sjekke det ut, gå til http: // localhost: 4000 / todos.
Nå som vi har en link til redigere
side, vi burde nok få det til å fungere!
Åpne modelladapteren igjen (/lib/model_adapters/todo.js
). Vi skal legge til i en laste
metode slik at vi kan laste en bestemt å gjøre
og bruk den på vår redigeringsside. Det spiller ingen rolle hvor du legger til det, men for nå la oss sette det mellom alle
metode og lagre
metode:
this.load = funksjon (id, tilbakeringing) for (var jeg i geddy.todos) hvis (geddy.todos [i] .id == id) return callback (null, geddy.todos [i]); tilbakeringing (melding: "Ikke funnet", null); ;
Denne belastningsmetoden tar et ID og en tilbakeringing. Det løper gjennom elementene i geddy.todos
og sjekker for å se om gjeldende element er id
passer inn i passet id
. Hvis det gjør det, kalles det tilbakeringingen, passerer å gjøre
gjenstand tilbake. Hvis den ikke finner en kamp, kalles det tilbakeringingen med en feil. Nå må vi bruke denne metoden i todos kontrollerens show handling.
Åpne opp din todos
kontrolleren igjen og ta en titt på det er redigere
handling. Det skal se slik ut:
this.edit = funksjon (req, resp, params) this.respond (params: params); ;
La oss bruke belastningsmetoden som vi nettopp har opprettet:
this.edit = funksjon (req, resp, params) var selv = dette; geddy.model.Todo.load (params.id, funksjon (feil, todo) self.respond (params: params, todo: todo);); ;
Alt vi gjør her, laster todo og sender det ned til malen som skal gjengis. Så la oss ta en titt på malen.
Åpne opp /app/views/todos/edit.html.ejs
. Nok en gang kommer vi ikke til å trenge params boilerplate, så la oss fjerne den. Lag din edit.html.ejs
se slik ut:
<%= partial('_form', params: params, todo: todo); %>
Dette bør se veldig ut som add.html.ejs
fil vi nettopp har redigert. Du vil legge merke til at vi sender en å gjøre
objekt ned til partielle samt params denne gangen. Den kule tingen er, siden vi allerede skrev partiet, er dette alt vi må gjøre for å få redigeringssiden til å vises riktig.
Start serveren på nytt, opprett en ny å gjøre
og klikk på linken for å se hvordan dette fungerer. La oss nå gjøre at oppdateringsknappen fungerer!
Åpne modelladapteren igjen og finn lagre
metode. Vi skal legge litt til det slik at vi kan spare over eksisterende å gjøre
s. Få det til å se slik ut:
this.save = funksjon (todo, ops, tilbakeringing) if (type tilbakering! = 'funksjon') callback = function () ; var todoErrors = null; for (var jeg i geddy.todos) // hvis den allerede er der, lagre den hvis (geddy.todos [i] .id == todo.id) geddy.todos [i] = todo; todoErrors = geddy.model.Todo.create (todo) .errors; returnere tilbakeringing (todoErrors, todo); todo.saved = true; geddy.todos.push (todo); returnere tilbakeringing (null, todo);
Dette løkker over alle todoene i geddy.todos
og hvis id
er allerede der, det erstatter det å gjøre
med den nye å gjøre
forekomst. Vi gjør noen ting her for å sikre at våre valideringer jobber med oppdatering, samt å lage - for å gjøre dette må vi trekke feil
eiendom av en ny modell forekomst og send det tilbake i tilbakeringingen. Hvis det bestått valideringer, vil det bare være udefinert og vår kode vil ignorere den. Hvis det ikke passerte, todoErrors
vil være en rekke valideringsfeil.
Nå som vi har det på plass, la oss jobbe på vår kontroller Oppdater
handling.
Gå videre og åpne kontrollenheten igjen og finn oppdateringen, det burde se slik ut:
this.update = funksjon (req, resp, params) // Lagre ressursen, og vis deretter elementsiden denne.redirect (controller: this.name, id: params.id); ;
Du vil redigere den slik at den ser slik ut:
this.update = funksjon (req, resp, params) var selv = dette; geddy.model.adapter.Todo.load (params.id, funksjon (feil, todo) todo.status = params.status; todo.title = params.title; todo.save (funksjon (feil, data) if ( feil) params.errors = err; self.transfer ('rediger'); else self.redirect (controller: self.name););); ;
Hva vi gjør her, laster den forespurte å gjøre
, redigere noen av sine egenskaper, og lagre å gjøre
en gang til. Koden vi nettopp skrev i modelladapteren, skal håndtere resten. Hvis vi får en feil tilbake, betyr det at de nye egenskapene ikke bestod validering, så vi overfører forespørselen tilbake til redigere
handling. Hvis vi ikke fikk en feil, vil vi bare omdirigere forespørselen tilbake til index
handling.
Gå videre og prøv det ut. Start serveren på nytt, opprett en ny å gjøre
, klikk på det er redigere lenke, endre status til ferdig
, og se at det blir oppdatert i index
. Hvis du vil bekrefte at du har valideringene dine, kan du prøve å endre tittel
til noe kortere enn 5 tegn.
La oss få den "Fjern" -knappen til å fungere.
Ved nå har vi en jobber til å gjøre listen søknad, men hvis du begynner å bruke det for en stund, vil det bli vanskelig å finne å gjøre
element som du leter etter på indekssiden. La oss få den "Fjern" -knappen til å fungere slik at vi kan holde vår liste fin og kort.
La oss åpne vår modelladapter igjen, denne gangen vil vi legge til en fjerne
metode der inne. Legg til dette rett etter lagre
metode:
this.remove = funksjon (id, tilbakeringing) hvis (type tilbakering! = 'funksjon') callback = funksjon () ; for (var jeg i geddy.todos) hvis (geddy.todos [i] .id == id) geddy.todos.splice (jeg, 1); returnere tilbakeringing (null); returnere tilbakeringing (melding: "Ikke funnet");
Denne er ganske enkel, det burde se mye ut som lastmetoden. Det løper gjennom alle å gjøre
s i geddy.todos
å finne id
som vi leter etter. Det sprer da det elementet ut av matrisen og kaller tilbakeringingen. Hvis den ikke finner det i arrayet, kalles det tilbakeringingen med en feil.
La oss bruke dette i vår kontroller nå.
Åpne kontrolleren din igjen og fingre på fjerne
handling. Det skal se slik ut:
this.remove = funksjon (req, resp, params) this.respond (params: params); ;
Rediger det slik at det ser slik ut:
this.remove = funksjon (req, resp, params) var selv = dette; geddy.model.adapter.Todo.remove (params.id, funksjon (err) hvis (err) params.errors = err; self.transfer ('rediger'); else self.redirect (controller: self .Navn); );
Vi passerer id
som vi fikk fra parametrene i form innlegget inn i fjerne
metode som vi nettopp har opprettet. Hvis vi får en feil tilbake, viderekobler vi tilbake til redigere
handling (vi antar at skjemaet har lagt inn feil info). Hvis vi ikke fikk en feilmelding, send bare forespørselen til index
handling.
Det er det! Vi er ferdige.
Du kan teste fjernfunksjonen ved å starte serveren på nytt, opprette en ny å gjøre
elementet, klikk på det, og klikk deretter på "Fjern" -knappen. Hvis du gjorde det riktig, bør du være tilbake på indekssiden med det aktuelle elementet fjernet.
I den neste opplæringen bruker vi http: //i.tvs fantastiske mongodb-wrapper-modul for å fortsette vår å gjøre
er i MongoDB. Med Geddy vil dette være lett; alt vi må bytte er modelladapteren.
Hvis du har spørsmål, vennligst legg igjen en kommentar her, eller åpne et problem på github.