Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can "sequelize.import()" import models from another file?

When I create a new model in the following way:

//user.js file
module.exports = function (sequelize, DateTypes) {

return sequelize.define("user", {
    email: {
        type: DateTypes.STRING,
        allowNull: false,
        unique: true,
        validate: {
            isEmail: true
        }
    },
    password: {
        type: DateTypes.STRING,
        allowNull: false,
        validate: {
            len: [7, 100]
        }
    }
});
};

and into db.js file where i built a new database:

var Sequelize = require('sequelize');
var env = process.env.NODE_ENV || "development"; // established if you work in production or in development mode
var sequelize;

if (env == "production") {
    sequelize = new Sequelize(process.env.DATABASE_URL, {
        "dialect": "postgres",

    });
} else {
    var sequelize = new Sequelize(undefined, undefined, undefined, {
        'dialect': 'sqlite',
        'storage': __dirname + '/data/dev-todo-api.sqlite' // location where you create a new sqlite database 
    });
}

var db = {};

db.todo = sequelize.import(__dirname + "/models/todo.js");
db.user = sequelize.import(__dirname + "/models/user.js");
db.sequelize = sequelize; //contain a settings of database
db.Sequelize = Sequelize;

module.exports = db;

I don't understand how user.js knows that sequelize (that I insert as a parameter into module.exports) is the instance of a sequelize package if it is situated into another file? Maybe because with sequelize.import('/user.js') it imports the entire sequelize package?

like image 748
Morris Avatar asked Nov 16 '16 20:11

Morris


2 Answers

See the definition of sequelize.import:

Sequelize.prototype.import = function(path) {
  // is it a relative path?
  if(Path.normalize(path) !== Path.resolve(path)){
    // make path relative to the caller
    var callerFilename = Utils.stack()[1].getFileName()
      , callerPath = Path.dirname(callerFilename);

    path = Path.resolve(callerPath, path);
  }

  if (!this.importCache[path]) {
    var defineCall = (arguments.length > 1 ? arguments[1] : require(path));
    if (typeof defineCall === 'object' && defineCall.__esModule) {
      // Babel/ES6 module compatability
      defineCall = defineCall['default'];
    }
    this.importCache[path] = defineCall(this, DataTypes);
  }

  return this.importCache[path];
};

Effectively it calls require on the path and then calls the result with the sequelize instance as its first argument. This is what ties the knot allowing the module to have a reference to the sequelize instance that imported it.

like image 54
Dan D. Avatar answered Nov 12 '22 00:11

Dan D.


Might be helpful. This is what that code looks like for me when compiled:

/**
 * Imports a model defined in another file
 *
 * Imported models are cached, so multiple calls to import with the same path will not load the file multiple times
 *
 * See https://github.com/sequelize/express-example for a short example of how to define your models in separate files so that they can be imported by sequelize.import
 * @param {String} path The path to the file that holds the model you want to import. If the part is relative, it will be resolved relatively to the calling file
 * @return {Model}
 */
import(path) {
  // is it a relative path?
  if (Path.normalize(path) !== Path.resolve(path)) {
    // make path relative to the caller
    const callerFilename = Utils.stack()[1].getFileName();
    const callerPath = Path.dirname(callerFilename);

    path = Path.resolve(callerPath, path);
  }

  if (!this.importCache[path]) {
    let defineCall = arguments.length > 1 ? arguments[1] : require(path);
    if (typeof defineCall === 'object') {
      // ES6 module compatibility
      defineCall = defineCall.default;
    }
    this.importCache[path] = defineCall(this, DataTypes);
  }

  return this.importCache[path];
}
like image 25
Andrew Avatar answered Nov 11 '22 23:11

Andrew