Tuesday, January 24, 2012

Introducing TrackMyRun

I’ve been working on a small pet project for a couple of weeks now, which I named TrackMyRun. I’m quite fanatic when it comes to running, doing about 130 runs a year. Currently I’m keeping track of all these runs in a simple spreadsheet, but off course, that’s certainly not “the geek way”. Hence the start of yet another pet project.

TrackMyRun is written using CoffeeScript, Node.js and Express. I’m also using the Bootstrap toolkit from Twitter for styling. I’m intending to actually use this small application for myself by hosting it on Heroku or some other cloud solution as soon as I’m able to finish the most essential features. It’s far from done yet, but you can already have a look at the source code on GitHub.  As always, suggestions are welcome.

Happy reading!

Saturday, January 21, 2012

Taking Toddler Steps with Node.js - Express Routing

In the previous post I provided a short introduction to Express, a web development framework built on top of connect that is heavily inspired by Sinatra. For this post we’ll dive into a couple of styles for dealing with routes in Express.

Express simply uses HTTP verbs for its routing API.

// Index
app.get('/runs', function(request, response) { });            

// New run 
app.get('/runs/new', function(request, response) { });

// Create a new run
app.post('/runs', function(request, response) { });

// Show run
app.get('/runs/:id', function(request, response) { });

// Edit run
app.get('/runs/:id/edit', function(request, response) { });

// Update run
app.put('/runs/:id', function(request, response) { });

// Delete run
app.delete('/runs/:id', function(request, response) { });

Well, that’s pretty much all that you need to get started. The routes that we specified here are treated as plain old regular expressions. Note that in order to make the put and delete routes work, we have to add a hidden field to the view.

<input name="_method" value="PUT" type="hidden">

But the thing that I personally struggled with the most was finding out a decent way to divide up these routes into separate modules without too much of a hassle. Most sample and demo applications out there that use Express usually have all their routes specified in a single app.js file. This is something that I don’t like very much as this can become unmaintainable faster that you might think. Roughly 2000 years ago, there was this great emperor (and many after him) who valued the principle of Divide and Conquer. In order to create maintainable applications, being able to divide up these routes is quite essential. There are several ways to do this.

Express Resource

This library enables us provide resourceful routing. As usual, express-resource can be installed using npm by using the following command:

 npm install express-resource

Using express-resource, we can create controller modules and use them from our main module. The following snippet shows how a simple controller looks like:

exports.index = function(request, response){
    response.send('Index runs');
};

exports.new = function(request, response){
    response.send('New run');
};

exports.create = function(request, response){
    response.send('Create run');
};

exports.show = function(request, response){
    response.send('Show run ' + request.params.id);
};

exports.edit = function(request response){
    response.send('Edit run ' + request.params.id);
};

exports.update = function(request, response){
    response.send('Update run ' + request.params.id);
};

exports.destroy = function(request, response){
    response.send('Delete run ' + request.params.id);
};

Now in the main module (app.js) we just have to add the following code:

var resource = require('express-resource')

// ...

application.resource('runs', require('./routes/runs'));

That’s it! Now all these routes are hooked up and ready to use. Express-resource has a few other neat features as well. Check out this episode from Node Tuts to learn more.

Although this seems like a good solution to divide up routes into controller modules, somehow it doesn’t resonate with me. All routes for a particular resource need to exist in the same module which still feels a bit unwieldy to me. I want to have an even more granular approach.

Super-duper Require

What I like to do is to separate routes based on their context:

  • runs/index.js ( index route )
  • runs/new.js ( new and create routes )
  • runs/show.js ( show route )
  • runs/edit.js ( edit and update routes )
  • runs/delete.js ( delete route )

Wouldn’t it be cool if we could just “require” the runs directory and hook up all routes exported by all the modules that exist in this directory? Well, meet super_duper_require! While still using express-resource, we can now add all these routes like so:

    application.resource('runs', super_duper_require(module, './routes/runs/'));

This is how the super_duper_require function looks like:

    _ = require('underscore');
    
    function super_duper_require(mod, path) {
        var mixin = {};
          fileSystem.readdirSync(path)
              .forEach(function(filename) {
                _.extend(mixin, mod.require(path + filename));
            });
    
          return mixin;
    };

We just use the magnificent underscore.js library here to hook things up. This is just one of the fancy ways to solve the granularity problem. If we don’t want to use the express-resource library, we can always accomplish the same thing by going “plain old school” style.

Plain Old School

This is how I currently set up routing with Express. We no longer need the express-resource library for setting up our routes, but we can still use the same granularity as shown earlier. We also need underscore.js again, just as in the previous example, in order to stitch things together.

    var routes = require('./routes');
    var routes.runs = _.extend(require('./routes/runs'), 
                               require('./routes/runs/new'),
                               require('./routes/runs/show'),
                               require('./routes/runs/edit'),
                               require('./routes/runs/delete'));
                               
    ...
    
    function bootstrapRoutes(application) {
        app.get('/runs', routes.runs.index);            
        app.get('/runs/new', routes.runs.new);
        app.post('/runs', routes.runs.create);
        app.get('/runs/:id', routes.runs.show);
        app.get('/runs/:id/edit', routes.runs.edit);
        app.put('/runs/:id', routes.runs.update);
        app.delete('/runs/:id', routes.runs.delete);
    }

Up until now I’m pretty happy with this approach. I would love to hear how others divide up their routes into several modules. So please let me know if there are other awesomely cool ways to deal with this. In the mean time, I hope this helps.

Until next time.