I have noticed when one creates a project using Express.js, the route handler functions are now separated from the main ‘app.js’ file. They are now placed in ‘./routes/index.js’. Given this situation, how does one now save a record to the database (in this case using MongoDB accessed via Mongoose).
Traditionally one would have had the route handler function in ‘app.js’, for example:
//Create document
app.post('/documents.:format?', function(req, res) {
var d = new Document(req.body);
d.user_id = req.currentUser.id;
d.save(function() {
switch (req.params.format) {
case 'json':
var data = d.toObject();
// TODO: Backbone requires 'id', but can I alias it?
data.id = data._id;
res.send(data);
break;
default:
req.flash('info', 'Document created');
res.redirect('/documents');
}
});
});
Under the new “layout” such call would be changed to something like the following (in ‘app.js’ file):
app.post('/documents.:format?', routes.add_documents);
With all the actual processing occurring in the file ‘./route/index.js’:
exports.add_documents = function(req, res){
// Processing goes here!
};
My question is how can one incorporate the original route handler function into this new add_documents function above? In particular, how can one access the database schema model (e.g. create new instance of ‘Document’) so that I can access the database save method?
Full contents of ‘app.js’ is follows:
var express = require('express')
, routes = require('./routes')
, mongoose = require('mongoose')
, models = require('./models')
, Document;
var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
app.set('db-uri', 'mongodb://localhost/namecards');
});
app.configure('production', function(){
app.use(express.errorHandler());
});
models.defineModels(mongoose, function() {
app.Document = Document = mongoose.model('Document');
db = mongoose.connect(app.set('db-uri'));
})
// Routes
app.get('/', routes.index);
app.get('/add', routes.add_form);
app.post('/add', routes.add_document);
app.listen(3000);
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
Content of ‘models.js’
function defineModels(mongoose, fn) {
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
/**
* Model: Document
*/
Document = new Schema({
'surname': String,
'given_name': String,
'org': String,
'phone': String
});
mongoose.model('Document', Document);
fn();
}
exports.defineModels = defineModels;
Content of ‘./routes/index.js’
/*
* GET home page.
*/
exports.index = function(req, res){
res.render('index', { title: 'Documents' });
};
/*
* GET add contact page.
*/
exports.add_form = function(req, res){
res.render('add', { title: 'Add Document' });
};
/*
* POST add contact page.
*/
exports.add_document = function(req, res){
// Save data to DB using mongoose.
};
I found a method that appears to work, which doesn’t involve a huge number of changes to the code originally generated by Express. All you have to do is import mongoose into the file containing the route handler functions a.k.a. the controllers, and then load the relevant model in the routing function (see exports.addProcess below).
Here is the modified contents of ‘./routes/index.js’