How to organize a node app that uses sequelize?
The short story
The trick in this case is not to initialize the model in the file but just to provide the necesary information for its initialization and let a centralized module take care of the models setup and instantiation.
So the steps are:
- Have several Model files with data about the model, like fields, relationships and options.
- Have a singleton module which loads all those files and setup all the model classes and relationships.
- Setup your singleton module at the app.js file.
- Get the model classes from the singleton module do not use
require
on your model files, load the models from the singleton instead.
The longer story
Here is a more detailed description of this solution with the corresponding source code:
http://jeydotc.github.io/blog/2012/10/30/EXPRESS-WITH-SEQUELIZE.html
EDIT: This is a very old answer! (read down for info)
It's old and limited in many ways!
-
First, as @jinglesthula mentioned in comments (and I experienced it too) - there are problems with requiring those files. It's because
require
doesn't work the same way asreaddirSync
! -
Second - you are very limited in relations - the code doesn't provide options to those associations so you are UNABLE to create
belongsToMany
as it needsthrough
property. You can make the most basic assocs. -
Third - you are very limited in model relations! If you read closely the code, you will see that relations is an Object instead of an Array, so if you want to make more than one associations of the same type (like having two times
belongsTo
) - you cannot! -
Fourth - You don't need that singleton thingy. Every module in nodejs is singleton by itself, so all this makes is pretty complex for no reason.
You should see Farm's answer! (The link to the article is broken, but I'll fix it with this official sample from sequelize: https://github.com/sequelize/express-example/blob/master/models/index.js - you can browse the whole project to get an idea of what's going on).
p.s. I'm editing this post as it's so upvoted that people won't even see any new answers (as I did).
Edit: Just changed the link to a copy of the same post, but in a Github Page
SequelizeJS has a article on their website which solves this problem.
Link is broken, but you can find the working sample project here and browse it. See edited answer above to see why this is a better solution.
Extract from article:
-
models/index.js
The idea of this file is to configure a connection to the database and to collect all Model definitions. Once everything is in place, we will call the method associated on each of the Models. This method can be used to associate the Model with others.
var fs = require('fs') , path = require('path') , Sequelize = require('sequelize') , lodash = require('lodash') , sequelize = new Sequelize('sequelize_test', 'root', null) , db = {} fs.readdirSync(__dirname) .filter(function(file) { return (file.indexOf('.') !== 0) && (file !== 'index.js') }) .forEach(function(file) { var model = sequelize.import(path.join(__dirname, file)) db[model.name] = model }) Object.keys(db).forEach(function(modelName) { if (db[modelName].options.hasOwnProperty('associate')) { db[modelName].options.associate(db) } }) module.exports = lodash.extend({ sequelize: sequelize, Sequelize: Sequelize }, db)
I've create a package sequelize-connect to help people deal with this issue. It follows the Sequelize suggested convention here: http://sequelize.readthedocs.org/en/1.7.0/articles/express/
Additionally it also functions a bit more like Mongoose in terms of its interface. It allows you to specify a set of locations where your models are located and also allows you to define a custom matching function to match your model files.
The usage is basically like this:
var orm = require('sequelize-connect');
orm.discover = ["/my/model/path/1", "/path/to/models/2"]; // 1 to n paths can be specified here
orm.connect(db, user, passwd, options); // initialize the sequelize connection and models
Then you can access the models and sequelize like so:
var orm = require('sequelize-connect');
var sequelize = orm.sequelize;
var Sequelize = orm.Sequelize;
var models = orm.models;
var User = models.User;
Hopefully this helps someone out.