MVC FTW!

I love it when I get stuff working after banging my head against a table for a lot longer than I would have liked. It's super satisfying.

As I mentioned in my last post, I came to the point a couple weeks ago where my app.js file was getting more than a little out of control. In particular, the routes section was unruly and overcrowded. So I did what any sane coder would do and decided to break things out into an MVC-like structure.

Thing is, since Node.js is so new, there aren't really any tutorials on exactly how to break a node app into easy-to-manage pieces.

I did learn about Locomotive, an MVC framework that hangs over Express. But Locomotive is really best when used at the very beginning of development, since it creates a whole slew of files and folders to make your organizational dreams come true (which is difficult to integrate when your app is already relatively well established). And then there's the issue of running your app with the command lcm server - which (a) doesn't translate well with nodemon (an absolute MUST for developers) and (b) is confusing, since server.app doesn't exist.

So, Locomotive, though very cool and by Jared Hanson, the maker of Passport, wasn't the right tool for the job. Not today, at least.

Instead, I went with separating things on my own. To start, I switched from Mongoose-Auth to Passport. Then I created a routes folder, with subfiles index.js, notes.js, and events.js:

  • app.js
  • accessDB.js
  • routes.js
  • routes/
    • index.js
    • notes.js
    • events.js
    <li>models/</li>
    
    • event.js
    • note.js
    • user.js
    <li>views/</li>
    
    • ...


Given the above tree, the next goal is to connect everything together:

[js title="app.js" smarttabs="true"]// Routes require('./routes')(app);[/js]

 

[js title="routes.js" smarttabs="true"]var passport = require('passport');

var start = require('./routes/index');
var notes = require('./routes/notes');
var events = require('./routes/events');

function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) { return next(); } res.redirect('/login'); }

module.exports = function(app) {

app.get('/', start.index);

app.get('/register', start.getRegister); app.post('/register', start.postRegister);

app.get('/login', start.login); app.post('/login', passport.authenticate('local', { successRedirect: '/account', failureRedirect: '/login' }) );

...[/js]

 

[js title="routes/index.js" smarttabs="true"]var db = require('../accessDB');

module.exports = {

// app.get('/'...) index: function(req, res) { res.render('index.jade', { locals: { title: 'CrowdNotes' } }); },

// app.get('/register'...) getRegister: function(req, res) { res.render('register.jade'); },

// app.post('/register'...) postRegister: function(req, res) { db.saveUser({ fname : req.param('name.first') , lname : req.param('name.last') , email : req.param('email') , password : req.param('password') }, function(err,docs) { res.redirect('/account'); }); },

...[/js]

And, surprisingly and perhaps magically, that's it!

Hopefully this will give people a bit of a better understanding of how to separate out code in Node.js - by all means, feel free to check out the CrowdNotes repo on GitHub!