I have a node project that uses express, orm and sqlite3.
I have multiple models. Currently each model is declared similar to this:
var orm = require('orm');
var db = orm.connect({database: ':memory:', protocol: 'sqlite'});
var schema = db.define('service', {
uptime: Number,
// ...
});
db.sync(function (err) {
!err && console.log("db synced!");
});
module.exports = schema;
No particularly pleasant across a dozen models to repeatedly require and connect.
I would like to tidy it up so I can connect in the app.js and then load in the models and use them as I normally would in the routes. However I can't get it working. This is what I am doing:
First I define the connect and define the models in app.js:
var service;
orm.connect(app.get('db-opt'), function(err,db){
!err && console.log("db connected!");
if (err){
throw err;
}
db.load('./models', function(err){
app.service = service = db.models.service;
!err && console.log("models loaded!");
});
db.sync(function(err){
!err && console.log("db synced!");
});
});
The models/index.js file looks like:
module.exports = function(db,fn){
db.define('service', {
uptime: Number,
// ...
});
return fn();
};
And the routes/services.js looks like:
var services = [];
exports.list = function(service){
return function(req, res){
service.find({}, function(err, services){
if (err){
return next(err);
}
res.render('services', {
title: 'Services',
services: services
});
});
};
};
And finally I connect the route like this in app.js:
app.get('/services', services.list(service));
I get the expected console messages but soon as I try to visit I get the following error:
TypeError: Cannot call method 'find' of undefined.
I have tried passing app.service and models.service to service.list but neither works giving the same error.
How can I cleanly load the models and have them accessible to the routes that require them?
Update: I can prove that the db.load call is working with the following code:
db.load('./models', function(err){
var services = [];
service = db.models.service;
service.find({}, function(err, services) {
if (err){
throw err;
}
});
!err && console.log("models loaded!");
});
As this gives a Error: SQLITE_ERROR: no such table: service
It appears I was close. I was under the assumption that the app.get('/', services.list(service)); would be called with whatever value was in service when it was invoked. So despite app.get(...) being executed (possibly) before the callback of orm.connect everything would be resolved correctly after the http.createServer(app). Not so.
Moving the app.get(..) to within the orm.connect call back causes it to work.
Thus:
// define models
var db = orm.connect(app.get('db-opt'), function(err,db){
!err && console.log("db connected!");
if (err){
throw err;
}
db.load('./models', function(err){
app.service = db.models.service;
!err && console.log("models loaded!");
});
db.sync(function(err){
!err && console.log("db synced!");
});
app.get('/', services.list(app.service));
// ...
});
While this is the method I will use, can anyone see a different way?