Att fortsätta en Todo lista med MongoDB och Geddy

I den här delstudiet kommer vi att dyka djupt för att skapa en listahanteringsapp i Node.js och Geddy. Det här är den sista posten i serien, där vi kommer att fortsätta vårt att göra föremål till MongoDB.

Som en snabb uppdatering, förra gången skapade vi vår att göra resurs och gjorde ett arbete för att göra listansökan, men data fanns endast i minnet. I den här handledningen fixar vi det!


Introduktion till MongoDB

MongoDB är en NoSQL-dokumentbutikdatabas som skapats av folket över på 10gen. Det är en bra databas för Node-appar eftersom den lagrar data i ett JSON-liknande format, och dess frågor är skrivna i JavaScript. Vi använder det för vår app, så låt oss få den inrättad.

Installera MongoDB

Gå till http://www.mongodb.org/downloads och hämta den senaste versionen för ditt operativsystem. Följ instruktionerna i readme därifrån. Se till att du kan börja mongod (och fortsätt och lämna den igång under hela denna handledning)

Det är värt att notera att du måste ha mongo att köra när som helst du vill att din app ska köras. De flesta ställer upp detta för att starta med sin server med ett uppstartskript eller något liknande.

Gjort? okej, låt oss gå vidare.

MongoDB-Wrapper

För vår app använder vi en modul som wraps den mongodb-native databasdrivrutinen. Detta förenklar koden som vi producerar, så låt oss få den installerad. CD in i din app och kör det här kommandot:

npm installera mongodb-wrapper

Om allt går bra borde du ha en mongodb-wrapper katalog i din node_modules katalog nu.


Ställa in din databas

Mongo är en väldigt lätt DB att arbeta med; du behöver inte oroa dig för att konfigurera tabeller, kolumner eller databaser. Bara genom att ansluta till en databas skapar du en! Och bara genom att lägga till i en samling gör du en. Så låt oss sätta upp det här för vår app.

Redigering av din init.js-fil

Vi behöver tillgång till vår DB-appövergripande, så låt oss konfigurera vår kod i config / init.js. Öppna den upp; det ska se ut så här:

// Lägg till uncaught-exception handler i prod-liknande miljöer om (geddy.config.environment! = 'Utveckling') process.addListener ('uncaughtException', funktion (err) geddy.log.error (JSON.stringify )););  geddy.todos = []; geddy.model.adapter = ; geddy.model.adapter.Todo = kräver (process.cwd () + '/lib/model_adapters/todo').Todo;

Låt oss lägga till i vår db-kod längst upp (och ta bort geddy.todos-arrayen när vi är på den):

var mongo = kräver ("mongodb-wrapper"); geddy.db = mongo.db ("localhost", 27017, "todo"); geddy.db.collection ( 'todos'); // Lägg till uncaught-exception handler i prod-liknande miljöer om (geddy.config.environment! = 'Utveckling') process.addListener ('uncaughtException', funktion (err) geddy.log.error (JSON.stringify )););  geddy.model.adapter = ; geddy.model.adapter.Todo = kräver (process.cwd () + '/lib/model_adapters/todo').Todo;

Först kräver vi mongodb-wrapper modul. Sedan ställer vi upp vår databas och lägger till en samling till den. Knappast någon uppsättning alls.


Skriv om din modell-adapter

Geddy bryr sig inte om vilken data-backend du använder, så länge du har en modelladapter skriven för den. Det innebär att den enda koden som du måste ändra i din app för att få din att göras till en databas finns i modelladaptern. Det sägs att detta kommer att bli en fullständig omskrivning av adaptern, så om du vill behålla din gamla minnesapp-app runt, vill du kopiera koden till en annan mapp.

Redigering av din räddningsmetod

Öppna din modell-adapter (lib / model_adapters / todo.js) och hitta spara metod. Det borde se ut så här:

this.save = funktion (todo, opts, callback) if (typ av callback! = 'function') callback = function () ;  var todoErrors = null; för (var jag i geddy.todos) // om det redan finns, spara det om (geddy.todos [i] .id == todo.id) geddy.todos [i] = todo; todoErrors = geddy.model.Todo.create (todo) .errors; returnera återuppringning (todoErrors, todo);  todo.saved = true; geddy.todos.push (todo); returnera återuppringning (null, todo); 

Gör det så här:

this.save = funktion (todo, opts, callback) // ibland behöver vi inte skicka en återuppringning om (typ av återuppringning! = 'funktion') callback = function () ;  // Mongo gillar inte det när du skickar funktioner till det // så låt oss se till att vi bara använder egenskaperna cleanTodo = id: todo.id, sparade: todo.saved, title: todo.title, status : todo.status; // Dubbelkontroll för att se om det här är giltigt todo = geddy.model.Todo.create (cleanTodo); om (! todo.isValid ()) return callback (todo.errors, null);  // Kontrollera om vi har det här att göra objekt redan geddy.db.todos.findOne (id: todo.id, funktion (err, doc) om (err) return callback (err, null);  // om vi redan har objektet, uppdatera det med de nya värdena om (doc) geddy.db.todos.update (id: todo.id, cleanTodo, function (err, docs) return callback (todo.errors, todo);; // om vi inte redan har att göra objekt, spara en ny en annan todo.saved = true; geddy.db.todos.save (todo, function err, docs) return callback (err, docs););); 

Bli inte för skämd av den här; Vi började med den mest komplicerade en först. Kom ihåg att vår spara Metoden måste redovisa både nya att göras och uppdatera gamla att göras. Så låt oss gå igenom denna kod steg för steg.

Vi använder samma återuppringningskod som vi gjorde tidigare - om vi inte har en återuppringning skickad till oss, använd bara en tom funktion.

Sedan sanerar vi vår att göra Artikel. Vi måste göra detta eftersom vår att göra objektet har JavaScript-metoder på det (som spara), och Mongo gillar inte det när du skickar objekt med metoder på dem. Så vi skapar bara ett nytt objekt med bara de egenskaper som vi bryr oss om det.

Då kontrollerar vi för att se om att göra är giltig. Om det inte är så kallar vi återuppringningen med valideringsfel. Om det är fortsätter vi vidare.

Om vi ​​redan har det här att göra objekt i db, vi kontrollerar db för att se om a att göra existerar. Det är här vi börjar använda mongodb-wrapper modul. Det ger oss ett rent API för att arbeta med vår db. Här använder vi db.todos.findOne () Metod för att hitta ett enda dokument som stämmer överens med vår fråga. Vår fråga är ett enkelt js-objekt - vi letar efter ett dokument vars id är samma som vår att göras id. Om vi ​​hittar en och det inte finns något fel använder vi db.todos.update () Metod för att uppdatera dokumentet med nya data. Om vi ​​inte hittar en använder vi db.todos.save () Metod för att spara ett nytt dokument med att göra objektets data.

I samtliga fall kallar vi en återuppringning när vi är färdiga, med eventuella fel som vi fick och de dokument som db återvände till oss skickades till det.

Redigering av hela metoden

Ta en titt på Allt metod ska det se ut så här:

this.all = function (callback) callback (null, geddy.todos); 

Låt oss se ut så här:

this.all = function (callback) var todos = []; gedy.db.todos.find (). sort (status: -1, titel: 1). toArray (funktion (err, docs) // om det finns ett fel, returnera tidigt om (err) return callback err, null); // iterera genom docs och skapa modeller av dem för (var jag i docs) todos.push (geddy.model.Todo.create (docs [i])) returnera återuppringning (null, todos);); 

Mycket enklare än spara metod tror du inte? Vi använder db.todos.find () metod för att få alla objekt i todos samling. Vi använder monogdb-wrappers api till sortera resultaten av status (i avkänd alfabetisk ordning) och av titel (i stigande alfabetisk ordning). Då skickar vi det till en matris, som utlöser frågan om att starta. När vi väl har fått tillbaka vår data kontrollerar vi om det finns några fel, om det finns, vi kallar återuppringningen med felet. Om det inte finns några fel fortsätter vi vidare.

Sedan gick vi igenom alla docs (de dokument som mongo gav tillbaka till oss), skapa nya att göra modell förekomster för var och en och tryck dem till en todos array. När vi är färdiga där kallar vi återkallningen, som passerar in i todos.

Redigering av belastningsmetoden

Ta en titt på "load" -metoden, det borde se ut så här:

 this.load = funktion (id, återuppringning) för (var jag i geddy.todos) om (geddy.todos [i] .id == id) return callback (null, geddy.todos [i]);  återuppringning (message: "För att inte hittas", null); ;

Låt oss se ut så här:

this.load = function (id, återuppringning) var todo; // hitta en todo i db geddy.db.todos.findOne (id: id, funktion (err, doc) // om det finns ett fel, returnera tidigt om (err) return callback (err, null) ; // om det finns ett dokument, skapa en modell av det om (doc) todo = geddy.model.Todo.create (doc); returnera återuppringning (null, todo);); ;

Den här är ännu enklare. Vi använder db.todos.findOne () metod igen. Den här gången är det bara vi behöver använda. Om vi ​​har ett fel, kallar vi återkallningen med det, om inte fortsätter vi vidare (ser ett mönster här ännu?). Om vi ​​har ett doc skapar vi en ny instans av att göra modell och ringa backbacken med den. Det är det för den där.

Redigering av borttagningsmetoden

Ta en titt på ta bort metod nu ska det se ut så här:

this.remove = funktion (id, återuppringning) om (typ av återuppringning! = 'funktion') callback = function () ;  för (var jag i geddy.todos) om (geddy.todos [i] .id == id) geddy.todos.splice (jag, 1); returnera återuppringning (null);  returnera återuppringning (message: "För att inte hittas"); ;

Låt oss se ut så här:

this.remove = funktion (id, återuppringning) om (typ av återuppringning! = 'funktion') callback = function () ;  geddy.db.todos.remove (id: id, funktion (err, res) callback (err);); 

Ta bort metoden är ännu kortare än den brukade vara. Vi använder db.todos.remove () Metod för att ta bort eventuella dokument med inlämnad id och ring uppringningen med ett eventuellt fel.


Tid för magi

Låt oss pröva vår app: CD in i ditt projekt katalog och starta servern med geddy. Skapa en ny att göra. Försök att redigera det, misslyckas med några valideringar och försök att ta bort det. Allt fungerar!


Slutsats

Jag hoppas att du har haft lust om Node.js, MongoDB och särskilt Geddy. Jag är säker på att du nu har en miljon idéer för vad du kan bygga med det, och jag skulle gärna höra om dem. Som alltid, om du har några frågor, lämna en kommentar här eller öppna ett problem på github.