website icon indicating copy to clipboard operation
website copied to clipboard

Best Practice documentation for import (associations)

Open chrisgo opened this issue 5 years ago • 14 comments

Awesome job getting to v5!

Possibly add a small example "best practice" of how to completely separate the model files in the documentation

http://docs.sequelizejs.com/manual/models-definition.html > Import

is very close but it does not address how to best put the associations into the separate model files

The examples here assume that you have imported all the models into this one file and then code all the associations after all the models have been imported

http://docs.sequelizejs.com/manual/associations.html

I believe most are using this an example prior to v5 https://codewithhugo.com/using-es6-classes-for-sequelize-4-models/

chrisgo avatar Mar 25 '19 20:03 chrisgo

👍 This has me stumped too

trappar avatar Mar 31 '19 01:03 trappar

There is an example here https://github.com/sequelize/express-example/blob/master/models/index.js

chrisgo avatar Apr 06 '19 05:04 chrisgo

Also:

http://docs.sequelizejs.com/manual/models-definition.html > Import

const Project = sequelize.import(__dirname + "/path/to/models/project")

module.exports = (sequelize, DataTypes) => {
  class Project extends sequelize.Model { }
  Project.init({
    name: DataTypes.STRING,
    description: DataTypes.TEXT
  }, { sequelize });
  return Project;
}

This for me crashes with:

TypeError: Class extends value undefined is not a constructor or null

The sequelize instance doesn't appear to have a reference to Model. What works for me is this:

const Project = sequelize.import(__dirname + "/path/to/models/project")

// In the mode file:
const Sequelize = require('sequelize')

module.exports = (sequelize, DataTypes) => {
  class Project extends Sequelize.Model { }
  Project.init({
    name: DataTypes.STRING,
    description: DataTypes.TEXT
  }, { sequelize });
  return Project;
}

brenc avatar Jun 10 '19 16:06 brenc

Also:

http://docs.sequelizejs.com/manual/models-definition.html > Import

const Project = sequelize.import(__dirname + "/path/to/models/project")

module.exports = (sequelize, DataTypes) => {
  class Project extends sequelize.Model { }
  Project.init({
    name: DataTypes.STRING,
    description: DataTypes.TEXT
  }, { sequelize });
  return Project;
}

This for me crashes with:

TypeError: Class extends value undefined is not a constructor or null

The sequelize instance doesn't appear to have a reference to Model. What works for me is this:

const Project = sequelize.import(__dirname + "/path/to/models/project")

// In the mode file:
const Sequelize = require('sequelize')

module.exports = (sequelize, DataTypes) => {
  class Project extends Sequelize.Model { }
  Project.init({
    name: DataTypes.STRING,
    description: DataTypes.TEXT
  }, { sequelize });
  return Project;
}

This for me crashes also,with: TypeError: Class extends value undefined is not a constructor or null. And i fix it with this method,is this a bug?

const Sequelize = require('sequelize')

module.exports = (sequelize, DataTypes) => {
  class Model extends Sequelize.Model {}
  Model.init({
    email: DataTypes.STRING,
    password: DataTypes.STRING
  }, {
    sequelize,
    modelName: 'user'
  })
  return Model
}

jackie1120 avatar Jun 27 '19 02:06 jackie1120

const Sequelize = require('sequelize')

module.exports = (sequelize, DataTypes) => {
  class Model extends Sequelize.Model {}
  Model.init({
    email: DataTypes.STRING,
    password: DataTypes.STRING
  }, {
    sequelize,
    modelName: 'user'
  })
  return Model
}

But associate not working while using import method

satheeshnatarajan avatar Jul 15 '19 11:07 satheeshnatarajan

Thanks for this issue. I was planning to do this for a while already... I really think this would help. I will try to get into this in a few days.

papb avatar Jul 15 '19 15:07 papb

Any update? I have the same issue with TypeError: Class extends value undefined is not a constructor or null. Solution with additional const Sequelize = require('sequelize') in each module file looks for me like dirty hack :disappointed:

ghost avatar Jul 31 '19 13:07 ghost

@irekg I still plan on getting into this, unfortunately I am more busy than expected, hopefully you can wait a bit more :grimacing:

papb avatar Jul 31 '19 13:07 papb

@papb I briefly looked at the code and it it looks like that all we need is another alias in /lib/sequelize.js.

// Aliases
Sequelize.prototype.fn = Sequelize.fn;
Sequelize.prototype.col = Sequelize.col;
Sequelize.prototype.cast = Sequelize.cast;
Sequelize.prototype.literal = Sequelize.literal;
Sequelize.prototype.and = Sequelize.and;
Sequelize.prototype.or = Sequelize.or;
Sequelize.prototype.json = Sequelize.json;
Sequelize.prototype.where = Sequelize.where;
Sequelize.prototype.validate = Sequelize.prototype.authenticate;
Sequelize.prototype.Model = Model; // <-- is it that simple or I'm missing something bigger?

It works fine for me with this alias. I can prepare PR if You like.

ghost avatar Jul 31 '19 13:07 ghost

@irekg Ah, okay, you are thinking of something much smaller than I was. If that single change helps you, I think it is super fine! Feel free to submit a PR.

papb avatar Jul 31 '19 14:07 papb

Also:

http://docs.sequelizejs.com/manual/models-definition.html > Import

const Project = sequelize.import(__dirname + "/path/to/models/project")

module.exports = (sequelize, DataTypes) => {
  class Project extends sequelize.Model { }
  Project.init({
    name: DataTypes.STRING,
    description: DataTypes.TEXT
  }, { sequelize });
  return Project;
}

This for me crashes with:

TypeError: Class extends value undefined is not a constructor or null

The sequelize instance doesn't appear to have a reference to Model. What works for me is this:

const Project = sequelize.import(__dirname + "/path/to/models/project")

// In the mode file:
const Sequelize = require('sequelize')

module.exports = (sequelize, DataTypes) => {
  class Project extends Sequelize.Model { }
  Project.init({
    name: DataTypes.STRING,
    description: DataTypes.TEXT
  }, { sequelize });
  return Project;
}

@brenc Looking at the source code https://github.com/sequelize/sequelize/blob/d041e77e275c3e950cedcdb3a625d891ea8b056b/lib/sequelize.js#L1311

I noticed that it might be possible to do:

module.exports = (sequelize, DataTypes) => {
  class Project extends sequelize.Sequelize.Model { }
  Project.init({
    name: DataTypes.STRING,
    description: DataTypes.TEXT
  }, { sequelize });
  return Project;
}

Haven't tried yet. I will test it tomorrow at work. IMHO If this works then it's the simplest workaround.


Update: tested. It works.

ghost avatar Jul 31 '19 17:07 ghost

@irekg Oh that's right!! So your PR wouldn't be needed after all...

papb avatar Jul 31 '19 17:07 papb

@papb Right. But I think that example in documentation should be updated.

ghost avatar Jul 31 '19 20:07 ghost

Definitely. I will keep this open as a docs issue.

papb avatar Jul 31 '19 22:07 papb