Node.js + express routes + mongoose, simple and separated

There are plenty of examples out there explaining how to develop a webserver in node.js using the express framework. There are also great books like Professional Node.js and Smashing Node.js introducing details about express among many other topics. But there is also, imho, a big problem: all of them show different ways to solve the same problem. In addition to that there were changes in the framework (Express has recently changed to version 4) and some documentation and samples could be deprecated, so if you are trying to learn anything that involves JS don't forget to check publication dates, even for this post!! I'll show how to develop a very simple guestbook from scratch, trying to apply the KISS principle: Keep It Simple Stupid! simple and clear, and trying to put every piece of code in its proper place (routes, models, views, etc...) Bad news: the express.js official page doesn't show how to do this. the good news, if you install express-generator (a must) you get a system command called express which will create project templates. So, let's start in a sort of "official" way. Without options we'll get a project using jade as a template engine and plain css.

express simple-express-mongoose
This creates a directory with that name and an app.js with this content:
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);

/// catch 404 and forward to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

/// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});


module.exports = app;

Let's simplify to leave only the routes:

var express = require('express');
var index = require('./routes');
var guestbook = require('./routes/guestbook');


var app = express();

app.use(express.static('public'));

app.use('/', index);
app.use('/guestbook', guestbook);

app.listen(3000, function () {
        console.log('Listening on port 3000');
})
Requiring all routes just once

Applications tend to grow and so we would have to require every route in the main entrypoint for express. Instead of that we can require just the routes/index.js

exports.home = require('./home');
exports.guestbook = require('./guestbook');

Now app.js has simplified route requires

var express = require('express');
var routes = require('./routes'); // This will require 'routes/index.js' !!

var app = express();

app.use(express.static('public'));

app.use('/', routes.home);
app.use('/guestbook', routes.guestbook);

app.listen(3000, function () {
        console.log('Listening on port 3000');
})

I've seen samples where all routes are added to express with just one line of code, but it wasn't working here for me.

Adding MongoDB support

Ok, now we want to show guestbook messages from a MongoDB database. As we are using mongoose, we must define a schema for each collection, and so we'll create a guestbook.js file in a models folder. Here we could try the same procedure used for routes. We create a models/index.js file which connects to MongoDB and exports all mongoose schemas. Here is models/index.js

/**
 * models/index.js
 * All models are here to import all of them just with one command
 * in the main app.js, and by the way we connect to MongoDB
 * Better to use an external config.. I know.
 * https://github.com/pello-io/simple-express-mongoose
 * Pello Altadill - http://pello.info
 */
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/blog');

// optionally:
//mongoose.set('debug', true);

exports.GuestBook = require('./guestbook');

And this is the schema definition for the guestbook collection, mongoose style. MongoDB is a schemaless database but this driver forces you to define a schema.

The routes

Routes are separated, one file for the home request, other file for guestbook requests, and so forth as the app grows. home.js is pretty straightforward: when we receive a get request, just render the index.jade

And this is the route for guestbook.js, with the get and the post. post saves data and then redirects to get case.

app.js, finally

Here you have. There are more modules to load to improve this sample app, but at least routes and models now are kept apart.

You can clone, download, copy-paste this project from git. Don't forget to get the required node modules to make it work!

by Pello Altadill 4 Hours ago - 8 hits

Setting different config files in Node.js

External config files When it comes to configuration options it is always desirable to avoid hardcoding config values in our code. Even more, if we are using different config values in development and production environments it is necessary an easy way to switch from one to another. This also becomes useful when your code is public but you want to hide some config files. In Node.j...

by Pello Altadill 2 Days ago - 52 hits

More »

Enabling basic authentication for MongoDB databases

MongoDB is extremely easy to install and run. If you are not able to make it work maybe you could feel more confortable using Access or even excel. Well, sorry for that. This short article is but a quick and dirty guide to enable basic authentication in mongodb, and how to create one database with its own user (not a superadmin) with just read/write permissions. If you run mongo...

by Pello Altadill 4 Days ago - 82 hits

More »

Python language basics

Python in 21 minutes (or so) For a developer is not enough to know one programming language, it is often said that is good to know many of them. After all the language is but a mere tool to build programs. Python has been around for many years and one of my pending task was to take a look at it. Some friends (@Eugenia4v,@Claw_Shadow,@D00m3dr4v3n) are always tellin...

by Pello Altadill 07/12/2014 23:51:05 - 184 hits

More »

A night out with Jasmine

A night out with Jasmine Unit testing is much more than a tool for ensuring that a program behaves as expected. Nowadays it's the key for new development techniques such as TDD and BDD in which you begin writing tests before the required code. It's all about requirements and behaviour; developers must focus on understanding the requirements instead of thinking about the way they implement the code. In the event that you've forgotten the fundamental benefits of unit testing here you have a quick...

by Pello Altadill 04/23/2014 00:37:18 - 1547 hits

More »

Arkapong

This a classic pong-like game that takes some ideas from Arkanoid. Basically two paddles try to hit the ball until one of them fails but, from time to time the rules can change if special bricks are touched. Red: invert ball direction White: triple ball Yellow: smaller paddles Blue: bigger paddles Green: speed up ball Orange: change...

by Pello Altadill 04/07/2014 07:35:33 - 1549 hits

More »

Getting started with Node

Few days ago, a very dear friend of mine came up to my place with a present. It was a nodejs book. This is a new or maybe it would be more accurate to say an emergent technology which brings back an old idea that I used to hear of long time ago: a server side javascript. That was something that was supposed to exist somewhere, as it was mentioned in the prefaces of many javascript related papers: ...

by Pello Altadill 03/17/2014 23:48:44 - 1805 hits

More »

Calcular el IBAN con php

Los organismos internaciones se han vuelto a poner de acuerdo para poner unificar los números de cuenta y gracias a ello todos los programadores y DBAs del mundo ya estamos enfrascados en la tarea de adaptar programas, validaciones, campos de las BBDD y un largo etcétera. En cada país el código de cuenta corriente puede variar y a través del IBAN se intenta unificar la forma de esa cuenta de tal forma que sea validable. ...

by Pello Altadill 01/18/2014 00:01:21 - 1872 hits

More »

MessageQueue con Spring

Hace unos meses salió aquí un ejemplo de ActiveMQ sin Spring ni nada, aunque lo relevante era mostrar la configuración y uso del servidor de mensajes. Vamos ahora a hacer exactamente lo mismo pero utilizando Spring. Cosa que tenía pendiente desde entonces. Al igual que suce...

by Pello Altadill 01/06/2014 00:08:52 - 1876 hits

More »