sequelize / cli

The Sequelize CLI
MIT License
2.53k stars 525 forks source link

Can't load model #645

Closed wuzi closed 6 years ago

wuzi commented 6 years ago

Hello, i'm creating a crud application with electron + vuejs, I used sequelize init and then created a model using sequelize model:generate --name User --attributes firstName:string,lastName:string,email:string, then i'm trying to load the models like this:

var models = require("../../database/models"); // The path is configured in .sequelizerc

But this line in models/index.js

var model = sequelize['import'](path.join(__dirname, file));

is returning Uncaught TypeError: Path must be a string. Received undefined.

Then i tried changing to

var model = sequelize['import'](path.resolve(__dirname, file));

And it seemed to work, but then i get the error on this line:

Object.keys(db).forEach(modelName => {

Saying Uncaught TypeError: Cannot assign to read only property 'exports' of object '#<Object>'

I wanted to use the automatic loader instead of loading every module separated if possible.

Thanks.

JoeHartzell commented 6 years ago

I'm guessing you are experiencing issue #366. Your relative path to the models is probably being generated incorrectly. When running the init the "models/index.js" file gets the var config = require(__dirname +... line generated incorrectly depending on the platform you are on. For example if that line looks like this

var config = require(__dirname + '/..\config\sequelize\config.js')[env];

Then it needs to be changed to flip all of the "\" to "/".

var config = require(__dirname + '/../config/sequelize/config.js')[env];

Let me know if that helps!

Side note - providing the code that is inside of your "models/index.js" file would be useful for troubleshooting. As well as your config file.

wuzi commented 6 years ago

I'm confused about the cause of this issue.

I'm using this boilerplate for the project and the files are looking like this:

models/index.js

'use strict';

var fs        = require('fs');
var path      = require('path');
var Sequelize = require('sequelize');
var basename  = path.basename(__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], config);
} else {
  var 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 => {
    var model = sequelize['import'](path.join(__dirname, file));
    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/user.js

'use strict';
module.exports = (sequelize, DataTypes) => {
  var User = sequelize.define('User', {
    firstName: DataTypes.STRING,
    lastName: DataTypes.STRING,
    email: DataTypes.STRING
  }, {});
  User.associate = function(models) {
    // associations can be defined here
  };
  return User;
};

config/config.json

{
  "development": {
    "username": null,
    "password": null,
    "database": "database_development",
    "host": null,
    "dialect": "sqlite",
    "storage": "database.db"
  },
  "test": {
    "username": null,
    "password": null,
    "database": "database_test",
    "host": null,
    "dialect": "sqlite",
    "storage": "database.db"
  },
  "production": {
    "username": null,
    "password": null,
    "database": "database_production",
    "host": null,
    "dialect": "sqlite",
    "storage": "database.db"
  }
}

.sequelizerc

const path = require('path');

module.exports = {
  'config': path.resolve('src/renderer/database/config', 'config.json'),
  'models-path': path.resolve('src/renderer/database', 'models'),
  'seeders-path': path.resolve('src/renderer/database', 'seeders'),
  'migrations-path': path.resolve('src/renderer/database', 'migrations')
}

And then i'm requiring it in the vuejs component like this:

var model = require('../database/models')

Maybe something messes up the path or imports somehow, i'm kinda lost.

Thank you!

wuzi commented 6 years ago

So I finally made it work! Basically I changed path.join to path.resolve And changed

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

to

for (var modelName in db) {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
}

It's probably not a problem with sequelize but some conflict with the boilerplate.

Thanks!