Make new model in Sequelize without model:generate? - javascript

Is it okay if I make models from copy-pasting? For instance, I made my first model User through Sequelize's model:generate. And then for other models, I just copy-pasted everything from the User model to my new models.
When doing db sync:
db.sequelize.sync({ force : true}).then(() => {
console.log("Drop and re-sync db.")
})
The new models won't create new tables. So I'm thinking copy-pasting for new models won't work. Is this right?
User model:
'use strict';
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
id: { type: DataTypes.BIGINT, allowNull: false, unique: true, primaryKey: true },
fbid: { type: DataTypes.BIGINT, allowNull: false, unique: true },
email: DataTypes.STRING,
first_name: DataTypes.STRING,
last_name: DataTypes.STRING,
photo_url: DataTypes.STRING
}, {});
User.associate = function(models) {
// associations can be defined here
};
return User;
};
And generated from copy-paste + modification of user model, I have: Country model
'use strict';
module.exports = (sequelize, DataTypes) => {
const Country = sequelize.define('Country', {
country_name: DataTypes.STRING
}, {});
Country.associate = function(models) {
// associations can be defined here
};
return Country;
};
Index.js generated by the cli in my models:
'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/config')[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 = 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;
Then after the generated models, after executing model:generate I transferred the generated User.js into a User folder. Then do the copy-paste, not sure if moving the files affect the registering of the models I created by copy-paste.

Based on the comments above, I realized that my index.js file (generated by Sequelize) wasn't looking for model files that ARE placed in subfolders. Instead, it ONLY looks for the model files that are in the root folder - same level of the index.js file.
So I posted this question: Javascript get all files in a folder that are inside another fold
I had to use the package glob to make the index.js file look for subfolders too.
So my index.js's content is now:
'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/config')[env];
const db = {};
const glob = require("glob")
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);
}
const files = glob.sync(__dirname + "/*/*.js")
files.forEach(file => {
const model = sequelize['import'](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;
To answer the specific question, NO. I don't have to do the commands all the time. I can copy-paste-edit new models instead.

Related

Sequelize, Express JS - Cannot read properties of undefined (reading 'findAll')

I am working with Express JS and Sequelize which is connected to a MSSQL database. I am unable to perform any requests as I am getting the error "Cannot read properties of undefined (reading 'findAll')". Can anyone help out with this one?
Below is my set up:
Invites Model:
module.exports = (sequelize, DataTypes) => {
const Invites = sequelize.define("Invites", {
Id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
Recipient: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true
}
},
Code: {
type: DataTypes.INTEGER,
allowNull: false,
validate: {
notEmpty: true
}
},
Score: {
type: DataTypes.INTEGER,
allowNull: false,
validate: {
notEmpty: true
}
},
Status: {
type: DataTypes.INTEGER,
allowNull: false,
validate: {
notEmpty: true
}
},
Created: {
type: DataTypes.DATE,
allowNull: false,
validate: {
notEmpty: true
}
},
ExpiresOn: {
type: DataTypes.DATE,
allowNull: false,
validate: {
notEmpty: true
}
}
});
return Invites;
};
inviteController:
const { invitesModel } = require('../models/Invites');
const getAllInvites = (req, res) => {
invitesModel.findAll().then((invites) => {
res.send(invites);
}).catch((err) => {
console.log(err);
})
};
module.exports = {
getAllInvites,
}
index.js:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
require('dotenv').config();
const db = require('./models');
const invitesController = require('./controllers/inviteController');
const cookieParser = require('cookie-parser');
const PORT = process.env.PORT || 5000;
app.use(cors()); //Cross origin resource sharing
app.use(express.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
//Get invite data
app.route('/api/invites').get(invitesController.getAllInvites);
db.sequelize.sync().then((req) => {
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
});
/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/config.json')[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);
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;
The require statement '../models/Invites' does not return an object with an invitesModel property.
You probably want to change your import statement to:
const { Invites } = require('../models');
And then use
Invites.findAll(...);
to query the Invites model.
If you're not sure what a require statement is grabbing, you can add a log statement to check:
const modelsObj = require('../models');
console.log(Object.keys(modelObj); // or console.log(JSON.stringify(modelsObj);
try add '?'
const getAllInvites = (req, res) => {
invitesModel?.findAll()?.then((invites) => {
res.send(invites);
}).catch((err) => {
console.log(err);
})
};

SequelizeEagerLoadingError: parent model is not associated to child

This is the parent model/table:
const { Sequelize, DataTypes } = require('sequelize');
const VerifyToken = require('./verifyToken');
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
password: DataTypes.STRING,
email: DataTypes.STRING,
}, {
tableName: 'users',
timestamps: false,
//syncOnAssociation: true
hierarchy: true,
underscored: true
});
User.associate = function (models) {
const {VerifyToken} = models;
User.hasOne(VerifyToken, {
as: 'verify_tokens',
foreign_key: 'user_id'
});
};
return User;
};
This is the child model:
const User = require('./user');
module.exports = (sequelize, DataTypes) => {
const VerifyToken = sequelize.define('VerifyToken', {
user_id: DataTypes.INTEGER,
token: DataTypes.STRING,
}, {
tableName: 'verify_tokens',
hierarchy: true,
underscored: true
});
VerifyToken.associations = function (models) {
const {User} = models;
VerifyToken.belongsTo(User);
};
return VerifyToken;
};
models/index.js file:
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/config.json')[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 = 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;
, but when I make a query like this:
const verifyToken = await models.VerifyToken.findOne({
where: {
token
},
include:{
model: models.User
}
});
I am getting this:
SequelizeEagerLoadingError: User is not associated to VerifyToken!
Please correct VerifyToken.associations with VerifyToken.associate
Remove a redundant import of const VerifyToken = require('./verifyToken'); from the User model definition.

Sequelize: create is not a function when model is generated from migration

I created this model from sequelize CLI
models/society.js
'use strict';
module.exports = (sequelize, DataTypes) => {
const Society = sequelize.define('Society', {
code: DataTypes.STRING,
name: DataTypes.STRING,
description: DataTypes.STRING
}, {});
Society.associate = function(models) {
// associations can be defined here
};
return Society;
};
Then this is my index.js file for configurations
'use strict'
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
const api = require('./routes')
app.use(bodyParser.urlencoded({extended: false}))
app.use(bodyParser.json())
app.use('/api', api)
const port = process.env.PORT || 3000
app.listen(port, ()=>{
console.log(`API REST running on http://localhost:${port}`)
})
The part of routes is this
routes/index.js
'use strict'
const express = require('express')
const api = express.Router()
const SocietyCtrl = require('../controllers/society')
api.post('/society', SocietyCtrl.createSociety)
module.exports = api
And finally it's just the controller
controllers/society.js
'use strict'
const Society = require('../models/society')
function createSociety(req, res){
console.log('POST /api/society/')
Society.create(req.body).then(created =>{
res.status(200).send({society: created})
})
}
module.exports = {
createSociety
}
The problem comes when I try to make POST, I get this following error:
Society.create is not a function
Can you tell me what I'm doing wrong?
This problem is not related to migration, however to solve this problem you have to do two steps:
1) Add new file in models directory called index.js which contain the following code
NOTE: make sure to edit sequelize config (with your environment) which starts in line 9 and ends in line 13 in file below (models/index.js)
'use strict';
const Sequelize = require('sequelize');
const fs = require('fs');
const path = require('path');
const basename = path.basename(__filename);
const db = {};
const sequelize = new Sequelize('database', 'username', 'password', {
host: 'localhost',
port: 3066,
dialect: /* one of 'mysql' | 'mariadb' | 'postgres' | 'mssql' */
});
fs.readdirSync(__dirname).filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
}).forEach(file => {
const model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
module.exports = db;
2) in controllers/society.js file do the following
replace const Society = require('../models/society'); with const db = require('../models/index'); or const db = require('../models');
replace Society.create with db.Society.create
like this:
'use strict'
const db = require('../models');
function createSociety(req, res){
console.log('POST /api/society/');
db.Society.create(req.body).then(created =>{
res.status(200).send({society: created})
});
}
module.exports = {
createSociety
}
To learn more I recommend you to check a github repository called express-example which developed by official sequelize team
Thanks Amjed!
But I didn't need to add index.js to models directory because sequelize already did.
However all I needed to do was:
'use strict'
const db = require('../models/index')
const Society = db.Society
And then it worked like it was supposed to.

OverwriteModelError: Cannot overwrite `teams` model once compiled

After several hours. Research in StackOverflow. There are a lot of articles about this issue. But I can't figure out what I'm wrong here.
My code:
models/Team.js
const mongoose = require('mongoose');
const { Schema } = mongoose;
const teamSchema = new Schema({
name: { type: String, minLength: 1, required: true },
description: { type: String },
});
mongoose.model('teams', teamSchema);
models/Division.js
const mongoose = require('mongoose');
const { Schema } = mongoose;
const divisionSchema = new Schema({
name: { type: String, minLength: 1, required: true },
description: { type: String },
});
mongoose.model('teams', divisionSchema);
And I was required in index.js
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const keys = require('./config/keys');
require('./models/Team');
require('./models/Division');
mongoose.Promise = global.Promise;
mongoose.connect(keys.mongoURI, { useNewUrlParser: true });
const app = express();
app.use(bodyParser.json());
require('./routes/teamRoutes')(app);
const port = process.env.PORT || 5000;
app.listen(port);
routes/teamRoutes.js
const mongoose = require('mongoose');
const Team = mongoose.model('teams');
module.exports = (app) => {
app.get('/api/teams', async (req, res) => {
const teamsList = await Team.find({});
res.send(teamsList);
});
};
If I delete require('./models/Division');, It works. Why is that?
If not, I got the error:
throw new mongoose.Error.OverwriteModelError(name);
^
OverwriteModelError: Cannot overwrite `teams` model once compiled.
mongoose.model('teams', divisionSchema);
'teams' should be 'division' in models/Division.js I guess

Sequelize can not import a model

In expressJs project, I try to use sequelize to interact with database.
This is my model/user.js :
module.exports = (sequelize, DataTypes) => {
sequelize.define('user', {
email: {
type: DataTypes.STRING,
unique: true
},
password: DataTypes.STRING
})
}
And this is models/index.js :
const fs = require('fs')
const path = require('path')
const Sequelize = require('sequelize')
const config = require('../config/config')
const db = {}
const sequelize = new Sequelize(
config.db.database,
config.db.user,
config.db.password,
config.db.options
)
fs
.readdirSync(__dirname)
.filter((file) =>
file !== 'index.js'
)
.forEach((file) => {
var a = path.join(__dirname, file);
const model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
})
db.sequelize = sequelize
db.Sequelize = Sequelize
module.exports = db
The problem is in this line
const model = sequelize.import(path.join(__dirname, file));
Which returns undefine to model variable.
What did I miss here? I appreciate any hint?
Whole code on Github : here
Problem could be because of a missing return
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', { // Missing return
email: {
type: DataTypes.STRING,
unique: true
},
password: DataTypes.STRING
})
}
Change to
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
email: {
type: DataTypes.STRING,
unique: true
},
password: DataTypes.STRING
});
return User;
}

Categories