Sequelize model loading in NodeJS

King James Enejo

I am currently studying using NodeJS, Express, PostgreSQL and Sequelize on Scotch.io then I came across this:

'use strict';

var fs        = require('fs');
var path      = require('path');
var Sequelize = require('sequelize');
var basename  = path.basename(module.filename);
var env       = process.env.NODE_ENV || 'development';
var config    = require(__dirname + '/../config/config.json')[env];
var db        = {};

if (config.use_env_variable) {
  var sequelize = new Sequelize(process.env[config.use_env_variable]);
} else {
  var sequelize = new Sequelize(config.database, config.username, config.password, config);
}

fs
  .readdirSync(__dirname)
  .filter(function(file) {
    return (file.indexOf('.') !== 0) && (file !== basename) & (file.slice(-3) === '.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].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

I am seeking an explanation of this code in plain terms. What exactly is happening here?

I do understand the part where we default to development if Node environment is not set but I need clarification of the file reading part i.e where fs begins.

vapurrmaid

Firstly, note that this code is generated by sequelize-cli by running sequelize init and is placed in a file called index.js located in a models/ folder.

1. The Configuration Environment

if (config.use_env_variable) {
  var sequelize = new Sequelize(process.env[config.use_env_variable]);
} else {
  var sequelize = new Sequelize(config.database, config.username, config.password, config);
}

This is helpful for when in production. As an example, I'll show you my code:

module.exports = {
  development: {
    dialect: 'postgres',
    username: '<username name>',
    password: 'test',
    database: '<db name>',
    host: 'localhost'
  },
  production: {
    dialect: 'postgres',
    dialectOptions: {
      ssl: true
    },
    protocol: 'postgres',
    use_env_variable: 'DATABASE_URL'
  }
}

Heroku sets a process variable DATABASE_URL that I simply point to. The username, password etc are obtained from this, rather than listing them explicitly in config.js, as development credentials are.

2. Importing/Reading Models

fs
  .readdirSync(__dirname)
  .filter(function(file) {
    return (file.indexOf('.') !== 0) && (file !== basename) & (file.slice(-3) === '.js');
  })
  .forEach(function(file) {
    var model = sequelize['import'](path.join(__dirname, file));
    db[model.name] = model;
  });

fs.readdirSync synchronously reads the directory given in its argument. In this case, it's __dirname, which is the directory that this index.js file is in. Here, the models you defined in models/ directory are pulled in. Notice that the filter function is just making sure that:

  • There are files to read
  • It excludes this file (ie not index.js)
  • They end in '.js'

Each model file is then keyed into the exports Object with the line db[model.name] = model;

3. Associating Each Model

Object.keys(db).forEach(function(modelName) {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

Lastly, once we have obtained all of the model files (from the previous read), we run each model's associate function, if it exists. This is a method that's defined in each model file as follows:

module.exports = (sequelize, DataTypes) => {
  var Model1 = sequelize.define('Model1',
    { ... })

  // Class Method
  Model1.associate = function (models) {
    Model1.belongsTo(models.Model2)
  }
  return Model1
}

4. Exported Use

Both an instance of your sequelize database (sequelize) and an instance of the Sequelize library are exported.

In this manner we can now do the following:

assume a directory structure of

  • models/
    • index.js
    • model1.js
    • model2.js

require('./models').Model1 // access to your models

This is how you'll import and use your models, rather than directly through their definition files. This ensures they're synced and associated properly.

Likewise we have access to sequelize:

require('./models')
  .sequelize.sync({ force: true }) // access to your sequelize db

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related