Morris
Morris

Reputation: 601

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?

Upvotes: 8

Views: 23073

Answers (2)

Andrew
Andrew

Reputation: 3959

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];
}

Upvotes: 3

Dan D.
Dan D.

Reputation: 74645

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.

Upvotes: 10

Related Questions