Attach Model to Sequelize Object

623 Views Asked by At

It has been a while since I used sequelize and I recently started a new setup with the sequelize-cli tool that appears to have a very templated approach to model generation and I'm trying to determine how I can access my model to make queries. In my attempt below, I at first thought I was accessing the model object incorrectly, but when I console log the sequelize object I noticed the Model property with an empty object. Is this technically where the model reference should come from? Is there something else I should be adjusting outside of initializing from the cli and generating the model in the same way?

Logging sequelize object in my API call:

import db from '../../models/index';

console.log(db) As you can see below models: {} is empty and from what I believe, should be populated with the users model defined in users.js

{
  sequelize: Sequelize {
    options: {
        ...
    },
    config: {
      ...
    },
    dialect: PostgresDialect {
      ...
    },
    queryInterface: PostgresQueryInterface {
      sequelize: [Circular],
      queryGenerator: [PostgresQueryGenerator]
    },
    models: {},
    modelManager: ModelManager { models: [], sequelize: [Circular] },
    connectionManager: ConnectionManager {
      ...
    }
  }, ...

Here is the index.js that was generated by the cli (Would love an explanation of how it is supposed to automatically recognize models):

/models/index.js

'use strict';

const fs = require('fs');
const path = require('path');
const { Sequelize } = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/sequelize.js')[env];
const db = {};

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

fs
  .readdirSync(__dirname)
  .filter(file => {
    return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
  })
  .forEach(file => {
    const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
    console.log(db[model.name])
    db[model.name] = model;
  });

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

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

module.exports = db;

/models/users.js:

'use strict';
const {
  Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
  class users extends Model {
    /**
     * Helper method for defining associations.
     * This method is not a part of Sequelize lifecycle.
     * The `models/index` file will call this method automatically.
     */
    static associate(models) {
      // define association here
    }
  };
  users.init({
    id: {
      type: DataTypes.UUID,
      defaultValue: Sequelize.UUIDV4
    },
    first_name: DataTypes.STRING,
    last_name: DataTypes.STRING,
    password: DataTypes.STRING,
    email: DataTypes.STRING,
    active: DataTypes.BOOLEAN,
    deleted: DataTypes.BOOLEAN
  }, {
    sequelize,
    modelName: 'users',
    createdAt: 'created_at',
    updatedAt: 'updated_at',
    deletedAt: 'deleted_at',
    paranoid: true,
    underscored: true,
    define: {
      freezeTableName: true,
      tableName: 'users'
    }
  });
  return users;
};
1

There are 1 best solutions below

0
On

It appears that the sequelize-cli generator for init and model doesn't always adapt to an app environment as expected. There are three issues with the boilerplate that is created.

  1. fs.readdirSync(__dirname) is syncing the parent directory on my computer, not my application directory
  2. const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes); runs into the same issue, which should be loading the js files within your model directory
  3. const Sequelize = require('sequelize'); is missing from the model generator, users.js which is referenced in const model = require(...)(sequelize, Sequelize.DataTypes);. Without it, it will throw an error that Sequelize is missing

Here is the correct code:

I used process.cwd() and appended '/models/' to correct the folder location issues.

index.js (Updated portion of code):

fs
  .readdirSync(process.cwd() + '/models/') // Updated
  .filter(file => {
    console.log(file)
    return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
  })
  .forEach(file => {
    console.log('file + Sequelize')
    console.log(Sequelize);
    const model = require('.' + path.join(__dirname, file))(sequelize, Sequelize.DataTypes); // Updated
    console.log(db[model.name])
    db[model.name] = model;
  });

users.js (Updated portion of code):

'use strict';
const Sequelize = require('sequelize');