Een RSS-feedslezer maken met de MEAN-stack

Dit artikel is een voortzetting van de Inleiding tot de MEAN-stack. De vorige post behandelde de installatie van de MEAN-stack en presenteerde ook wat we na de installatie hebben bereikt in termen van de directorystructuur. Nu is het tijd voor een aantal echte coderingen!

Wat we gaan bouwen

We zullen een RSS-feedlezer bouwen met behulp van de MEAN-stack. Met de toepassing kan de gebruiker zijn lijst met feeds beheren door een nieuwe feed toe te voegen, een bestaande feed te verwijderen, een bestaande feed te wijzigen en natuurlijk een lijst te bekijken van alle feeds waarin de gebruiker is geïnteresseerd.

De gebruiker moet zich verifiëren om toegang te hebben tot de toepassing, zodat de feeds van de ene gebruiker niet zichtbaar zijn voor anderen en, het belangrijkst, voor gebruikers die niet zijn aangemeld. Zoals we in het vorige artikel hebben gezien, wordt de stapel geleverd met een volledig authenticatiemechanisme is al geïmplementeerd, zodat we het kunnen gebruiken zonder verdere aanpassingen.

De URL's van de feed worden opgeslagen in een Mongo-database op de server, zodat ze ook na het afmelden of na het sluiten van de browser beschikbaar zijn.

De laatste feeds worden getoond aan de gebruiker op de hoofdpagina en ze tonen de titel van het artikel, een uittreksel en laten de gebruiker op de titel klikken om het volledige bericht te lezen.

De gebruiker heeft ook de mogelijkheid om de feeds op verschillende criteria te filteren.

In dit eerste deel bespreken we de implementatie van het servergedeelte van onze applicatie (de backend). We zullen een REST-API implementeren om te reageren op de verzoeken van gebruikers om feeds te bekijken, maken, verwijderen en wijzigen.

Gelukkig voor ons biedt de MEAN-stack ons ​​zo'n API voor het verwerken van de artikelen die kunnen worden gemaakt. We zullen deze API aanpassen om te reageren op onze behoefte aan het verwerken van de feed-URL's. Dit is de reden waarom we de boilerplate-code gebruiken om deze aan te passen en aan te passen aan de behoeften van onze applicatie. Dus laten we dat doen!

De routes

Laten we even nadenken over de routes waarop onze app moet reageren. De onderstaande afbeelding laat zien wat we verwachten te hebben: 

Laten we nu het bestand openen app / routes / articles.js. Als we kijken naar de inhoud ervan, zien we dat dit is wat we willen hebben, maar toegepast op de artikelen. Dus we moeten het een beetje aanpassen om aan onze behoeften te voldoen. Wijzig eerst de naam van articles.js naar feeds.js. Pas het dan aan zoals hieronder getoond:

 // app / routes / feeds.js 'gebruik strict'; var feeds = require ('... / controllers / feeds'); var authorization = require ('./ middlewares / authorization'); // Feeds autorisatie helpers var hasAuthorization = function (req, res, next) if (req.feed.user.id! == req.user.id) return res.send (401, 'Gebruiker is niet geautoriseerd') ;  volgende (); ; module.exports = functie (app) app.get ('/ feeds', feeds.all); app.post ('/ feeds', authorization.requiresLogin, feeds.create); app.get ('/ feeds /: feedId', feeds.show); app.put ('/ feeds /: feedId', authorization.requiresLogin, hasAuthorization, feeds.update); app.del ('/ feeds /: feedId', authorization.requiresLogin, hasAhorhorization, feeds.destroy); // Voltooien met het instellen van de feedId param app.param ('feedId', feeds.feed); ; 

Voor degenen die bekend zijn met het Express-framework, moet dit niets nieuws zijn, maar voor het geval, laten we het snel doornemen. We beginnen met het eisen van de feeds controller (die we zo meteen zullen zien) en de autorisatie middleware (die de MEAN stack ons ​​geeft).

Dan hebben we de hasAuthorization () functie, die de vergelijkt ID kaart van de gebruiker die de feed wil manipuleren met de ID kaart van de ingelogde gebruiker en retourneert een fout als deze niet hetzelfde is. De next () function is een callback waarmee de volgende laag in de middleware-stapel kan worden verwerkt.

In het laatste deel exporteert onze code de routes zoals beschreven in de bovenstaande tabel, waarbij de beveiligingsvereisten worden geïmplementeerd.

De modellen

Het model van de toepassing maken met behulp van mangoest is een briesje. Hernoem de app \ modellen \ article.js naar app \ modellen \ feed.js en voer de volgende wijzigingen uit:

 'gebruik strikt'; / ** * Module afhankelijkheden. * / var mongoose = vereisen ('mangoest'), Schema = mongoose.Schema; / ** * Feeds-schema. * / var FeedsSchema = nieuw schema (feedUrl: type: String, standaard: ", trim: true, gebruiker: type: Schema.ObjectId, ref: 'User'); / ** * Statics * / FeedsSchema.statics.load = function (id, cb) this.findOne (_id: id). Vullen ('user', 'name username'). Exec (cb);; mongoose.model ('Feeds' , FeedsSchema); 

We definiëren onze databasestructuur hier als volgt: we hebben een feeds-tabel met een feedUrl string type veld en een verwijzing naar a gebruiker welke de ID kaart van de huidige aangemelde gebruiker. Merk op dat we niet omgaan met het creëren van een ID kaart voor onze documenten hier, want dit wordt voor ons verzorgd door het MongoDB-systeem.

Ten slotte definiëren we een laden() functie die de documenten in de database filtert op basis van de ID kaart van de huidige aangemelde gebruiker.

De controller

De controller is verantwoordelijk voor het implementeren van de functies die door de router worden genoemd, wanneer om een ​​specifieke route wordt gevraagd. Alle noodzakelijke functies voor de CRUD-bewerkingen die we uitvoeren, worden geïmplementeerd in de controller. Laten we ze één voor één bekijken en de implementatiedetails bekijken.

Op dit punt zou je een patroon moeten opmerken. Ten eerste, vergeet niet om de naam te wijzigen app / controllers / articles.js bestand naar app / controllers / feeds.js.

Een feed maken

Om een ​​feed te maken, implementeren we de create () functie:

 / ** * Maak een feed * / exports.create = functie (req, res) var feed = new Feeds (req.body); feed.user = req.user; feed.save (functie (err) if (err) return res.send ('users / signup', errors: err.errors, feed: feed); else res.jsonp (feed); ); ; 

Eerst maken we een voeden variabele op basis van de feeds model. Vervolgens voegen we aan deze variabele de verwijzing toe naar de huidige aangemelde gebruiker die moet worden opgeslagen. Ten slotte noemen we de modellen opslaan methode om het document in de database op te slaan. Na een fout gaan we terug naar het aanmeldingsformulier, omdat de gebruiker waarschijnlijk niet is aangemeld. Als het document is aangemaakt, retourneren we het nieuwe document aan de beller..

Een feed aanpassen

 / ** * Een feed bijwerken * / exports.update = function (req, res) var feed = req.feed; feed = _.extend (feed, req.body); feed.save (functie (err) if (err) return res.send ('users / signup', errors: err.errors, feed: feed); else res.jsonp (feed); ); ; 

We noemen Lodash's uitbreiden methode om de eigenschappen van de feed te wijzigen met die van de gebruiker. Dan de opslaan methode van het model slaat de gewijzigde gegevens op in de database.

Een feed verwijderen

 / ** * Een feed verwijderen * / exports.destroy = function (req, res) var feed = req.feed; feed.remove (function (err) if (err) return res.send ('users / signup', errors: err.errors, feed: feed); else res.jsonp (feed); ); ; 

Heel eenvoudig, toch? Het model heeft een verwijderen methode die ons probleem vrij gemakkelijk oploste.

Feeds worden weergegeven

Het weergeven van alle feeds is de taak van het clientgedeelte van onze applicatie. De server retourneert alleen de benodigde gegevens:

 / ** * Lijst met feeds * / exports.all = functie (req, res) Feeds.find (). Sort ('- created'). Populate ('user', 'feedUrl'). Exec (function (err , feeds) if (err) res.render ('error', status: 500); else res.jsonp (feeds);); ; 

De code voert een zoekopdracht uit in de database die de gebruiker en de feedUrl. Als vind mislukt, er wordt een serverfout geretourneerd, anders worden alle gevonden feeds geretourneerd.

Een enkele feed wordt weergegeven met behulp van het volgende:

 / ** * Een feed weergeven * / exports.show = function (req, res) res.jsonp (req.feed); ; 

... die dan een hulpfunctie gebruikt:

 exports.feed = function (req, res, next, id) Feeds.load (id, functie (err, feed) if (err) return next (err); if (! feed) retourneer volgende (nieuwe fout (' Kan feed '+ id) niet laden); req.feed = feed; next ();); ; 

... die een specifieke feed laadt op basis van zijn ID kaart (die zal worden verpakt in de URL).

De volledige code zou dit moeten houden:

 // app / controllers / feeds.js 'use strict'; var mongoose = require ('mongoose'), Feeds = mongoose.model ('Feeds'), _ = require ('lodash'); exports.feed = function (req, res, next, id) Feeds.load (id, functie (err, feed) if (err) return next (err); if (! feed) retourneer volgende (nieuwe fout (' Kan feed '+ id) niet laden); req.feed = feed; next ();); ; / ** * Een feed weergeven * / exports.show = function (req, res) res.jsonp (req.feed); ; / ** * Lijst met feeds * / exports.all = functie (req, res) Feeds.find (). Sort ('- created'). Populate ('user', 'feedUrl'). Exec (function (err , feeds) if (err) res.render ('error', status: 500); else res.jsonp (feeds);); ; / ** * Maak een feed * / exports.create = functie (req, res) var feed = new Feeds (req.body); feed.user = req.user; feed.save (functie (err) if (err) return res.send ('users / signup', errors: err.errors, feed: feed); else res.jsonp (feed); ); ; / ** * Een feed bijwerken * / exports.update = function (req, res) var feed = req.feed; feed = _.extend (feed, req.body); feed.save (functie (err) if (err) return res.send ('users / signup', errors: err.errors, feed: feed); else res.jsonp (feed); ); ; / ** * Een feed verwijderen * / exports.destroy = function (req, res) var feed = req.feed; feed.remove (function (err) if (err) return res.send ('users / signup', errors: err.errors, feed: feed); else res.jsonp (feed); ); ; 

Is de REST-API voltooid??

Nou bijna. Op dit moment hebben we het clientgedeelte van de toepassing niet geïmplementeerd om te bewijzen dat de code werkt. Ik heb de unit tests voor de code ook niet gepresenteerd, omdat het niet zo ingewikkeld is en ik wilde het aan jou overlaten als een oefening.

We kunnen de code testen met de Postman - REST Client-applicatie die beschikbaar is in Google Chrome.

Een feed maken

Installeer Postman als je het nog niet hebt en configureer het als volgt:

Alle feeds bekijken

Een enkele feed bekijken

De resterende delen van de code zijn gemakkelijk te verifiëren, dus maak plezier met Postman en je nieuwe applicatie.

Conclusie

Het gebruik van een framework of boilerplate code kan in sommige situaties nuttig zijn en je erg productief maken. Zoals u in dit artikel hebt gezien, is het implementeren van de REST-API die nodig is voor onze toepassing beperkt tot het uitvoeren van kleine wijzigingen in de boilerplate-code. Natuurlijk kan het voor meer complexe toepassingen noodzakelijk zijn om meer te doen dan dat, maar toch kan het hebben van een startpunt nuttig zijn.

.