Alors, le moteur de blog, c'est parti, et en couleur!
Donc, on part de ça:
app.js
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 var express = require('express'); var http = require('http'); var path = require('path'); var app = express(); app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); app.get('/', function (req, res) { res.render({title: 'je suis la page index'}); }); http.createServer(app).listen(3000, function () { console.log('Le serveur ecoute sur le port 3000'); });
views/index.jade
Et on va faire le minimum syndical, à savoir:Code:
1
2
3
4
5
6
7
8
9
10 <!DOCTYPE html> <html> <head lang="fr"> <meta charset="UTF-8"> <title>{{title}}</title> </head> <body> <h1>{{title}}</h1> </body> </html>
- un fil avec tous les articles tronqués sur la page principale
- une page pour chaque article
- une page édition
Pour la persistance, on va faire ça avec mongoose, un odm pour mongo. On aurait pu utiliser node-mongodb-native, plus bas niveau, mais euh... pas envie... et honnêtement, mongoose rend bien des services et permet une structuration des données.
Comme je ne suis pas fan de ejs, on va continuer avec jade :P
// app.js
J'ai donc ma persistance, j'ai ajouté deux "controlleurs" pour ajouter des d'articles à mon blog, et modifié le moteur de template, en créant un layoutCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 var express = require('express'); var http = require('http'); var path = require('path'); var mongoose = require('mongoose'); var emphasis = require('emphasis'); mongoose.connect('mongodb://localhost/tuto'); // Je me connecte à la bdd // Mon Objet Article var ArticleSchema = mongoose.model('Article', { title: String, desc: String, content: String, url: String, createAt: { type: Date, default: Date.now } }); var app = express(); app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); app.get('/', function (req, res) { res.render('index', {title: 'je suis la page index'}); }); app.get('/create', function(req, res) { // j'affiche mon formulaire res.render('create'); }); app.post('/create', function(req, res) { // je traite mon formulaire var article = new ArticleSchema({ title: req.body.title, desc: req.body.desc, content: req.body.content, url: emphasis(req.body.title) }); article.save(function(err) { if (err) throw err; res.redirect('/' + article.url); }); }); http.createServer(app).listen(3000, function () { console.log('Le serveur ecoute sur le port 3000'); });
// layout.jade
// index.jadeCode:
1
2
3
4
5
6
7
8
9
10 doctype html html head(lang="fr") meta(charset="UTF-8") block title title Le tuto qui déchire // valeur par defaut body block body
// create.jade ultra-minimale!Code:
1
2
3
4 extends ./layout block body h1 #{title}
Tu peux donc lancer ton server et aller à l'url http://localhost:3000/create pour y voir ton formulaire. Tu le rempli, puis tu valide pour sauvegarder et ...Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 extends ./layout block title title Créer un nouvel article block body form(method="post", action="/create") div input(type="text", name="title", placeholder="Le titre de l'article") div textarea(name="desc", placeholder="meta description") div textarea(name="content", placeholder="Le contenu de l'article au format markdown", rows="30") input(type="submit", value="Valider")
Ca ne marche pas... car req.body n'existe pas... bha oui, il faut ajouter le module bodyparser pour parser le resultat de mon post et creer l'objet body.Code:TypeError: Cannot read property 'title' of undefined
et voila, ton article est en base, et tu es rediriger vers une page qui n'existe pas encore. avant cela, deux trois choses:Code:
1
2
3
4
5
6
7 app.set('view engine', 'jade'); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.get('/', function (req, res) {
pour info emphasis, c'est un petit module avec deux fonctions dedans... fait par moi-même pour gérer l'accentuation et les caractères spéciaux. Il casse pas trois pates à un canard, mais cela m'evite d'avoir à les refaires dans tous mes projets. Remarque il existe peut-être mieux ailleurs.
ensuite, j'ai tout dans mon app.js, là ca va encore mais cela va devenir l'enfer dans pas longtemps, on va donc réorganiser un peu.
On exporte le schema de Article dans un dossier "models":
// models/article.js
Schema.set(collection, 'foo') permet de spécifier le nom de la collection en bdd, ici "articles" au lieu de "Article".Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 var mongoose = require('mongoose'); var Schema = mongoose.Schema({ title: String, desc: String, content: String, url: String, createAt: { type: Date, default: Date.now } }); Schema.set('collection', 'articles'); module.exports = mongoose.model('Article', Schema);
Pour y acceder, dans notre app.js, un simple require:
ensuite on va sortir les controlleurs dans un dossier "routes" (ou ce que tu veux en fait)Code:
1
2
3
4
5 var Article = require('./models/article'); (...) var article = new Article({ title: req.body.title, (...)
// routes/index.js
// routes/create.jsCode:
1
2
3
4
5
6
7
8 var express = require('express'); var router = express.Router(); router.get('/', function (req, res) { res.render('index', {title: 'je suis la page index'}); }); module.exports = router;
// app.jsCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 var express = require('express'); var router = express.Router(); var emphasis = require('emphasis').normalize; var Article = require('../models/article'); router.get('/', function(req, res) { // j'affiche mon formulaire res.render('create'); }); router.post('/', function(req, res) { // je traite mon formulaire var url = emphasis(req.body.title); var article = new Article({ title: req.body.title, desc: req.body.desc, content: req.body.content, url: url }); article.save(function(err) { if (err) throw err; res.redirect('/' + url); }); }); module.exports = router;
On crée une instance de Router(), qui devient notre racine, comme tu peux le voir dans create.js, on je ne mentionne pas le 'create',Code:
1
2
3
4 (...) app.use('/', require('./routes/index')); app.use('/create', require('./routes/create')); (...)
et on le monte dans notre app.js, où l'on spécifie l'url de "montage". y'a plein de truc rigolo à faire avec le router de express (en particulier avec la v4), mais c'est un article à lui tout seul...
voici donc notre arborescence:
+models- article.js+node_modules
+routes- create.js+views
- index.js- create.jade- app.js
- index.jade
- layout.jade
et notre app.js
reste plus qu'a ajouter la page des articles, puis la page index avec tous les articles tronqués, pour avoir notre base, mais là je fais une pose ;)Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 // app.js var express = require('express'); var http = require('http'); var path = require('path'); var mongoose = require('mongoose'); var bodyParser = require('body-parser'); mongoose.connect('mongodb://localhost/tuto'); // Je me connecte à la bdd var app = express(); app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use('/', require('./routes/index')); app.use('/create', require('./routes/create')); http.createServer(app).listen(3000, function () { console.log('Le serveur ecoute sur le port 3000'); });