I am using node + express to create a simple REST API, and am trying to separate out routing logic from db logic. I am having a problem getting access to the DB from the routes.
Here is my server.js code:
var express = require('express')
, path = require('path')
, http = require('http')
, mongo = require('mongodb');
// Configure Express app
var app = express();
app.configure(function () {
app.set('port', process.env.PORT || 3000);
app.use(express.logger('dev')); /* 'default', 'short', 'tiny', 'dev' */
app.use(express.bodyParser()),
app.use(express.static(path.join(__dirname, 'public')));
});
// Configure DB
var Server = mongo.Server
, Db = mongo.Db
, BSON = mongo.BSONPure
, server = new Server('localhost', 27017, {auto_reconnect: true})
, db = new Db('mydb', server, {safe: true});
// Open DB to see if we need to populate with data
db.open(function(err, db) {
if(!err) {
console.log("Connected to 'mydb' database");
var Post = require('./routes/posts')
, post = new Post(db);
// Set the routes
app.get('/:org/posts', post.find);
app.get('/:org/posts/:id', post.get);
app.post('/:org/posts', post.add);
app.put('/:org/posts/:id', post.update);
app.delete('/:org/posts/:id', post.remove);
// Fire up the server
http.createServer(app).listen(app.get('port'), function () {
console.log("Express server listening on port " + app.get('port'));
});
}
});
and here is the logic in the post.js file:
var Post = function(db) {
this.db = db;
};
Post.prototype.get = function(req, res) {
var id = req.params.id;
var org = req.params.org;
var db = this.db;
console.log('Retrieving post: ' + id + ' from org: ' + org);
db.collection('ads', function(err, collection) {
collection.findOne({'_id':new BSON.ObjectID(id), 'org':org}, function(err, item) {
res.send(item);
});
});
};
Post.prototype.find = function(req, res) {
var org = req.params.org;
var db = this.db;
console.log('Finding posts for org: ' + org);
db.collection('posts', function(err, collection) {
collection.find({'org':org}).toArray(function(err, items) {
res.send(items);
});
});
};
Post.prototype.add = function(req, res) {
var org = req.params.org;
var post = req.body;
var db = this.db;
console.log('Adding post: ' + JSON.stringify(post) + ' for org: ' + org);
db.collection('posts', function(err, collection) {
collection.insert(post, {safe:true}, function(err, result) {
if (err) {
res.send({'error':'An error has occurred'});
} else {
console.log('Success: ' + JSON.stringify(result[0]));
res.send(result[0]);
}
});
});
};
Post.prototype.update = function(req, res) {
var id = req.params.id;
var org = req.params.org;
var post = req.body;
var db = this.db;
delete post._id;
console.log('Updating post: ' + id + ', org: ' + org);
console.log(JSON.stringify(post));
db.collection('posts', function(err, collection) {
collection.update({'_id':new BSON.ObjectID(id)}, post, {safe:true}, function(err, result) {
if (err) {
console.log('Error updating post: ' + err);
res.send({'error':'An error has occurred'});
} else {
console.log('' + result + ' document(s) updated');
res.send(post);
}
});
});
};
Post.prototype.remove = function(req, res) {
var id = req.params.id;
var org = req.params.org;
var db = this.db;
console.log('Deleting post: ' + id + ', org: ' + org);
db.collection('posts', function(err, collection) {
collection.remove({'_id':new BSON.ObjectID(id), 'org':org}, {safe:true}, function(err, result) {
if (err) {
res.send({'error':'An error has occurred - ' + err});
} else {
console.log('' + result + ' document(s) deleted');
res.send(req.body);
}
});
});
};
module.exports = Post;
I would think that the post object would hold on to the db reference for use when it is called from the routes, but I get the following error:
TypeError: Cannot call method 'collection' of undefined
at Post.find (../routes/posts.js:23:6)
Can anyone point me in the right direction? Many thanks