Before create doesn't work on my sequelize model
I created a template, but for some reason my before create doesn't work and I don't know what it can be anymore.
async createUser(req,res){
const { name,email,login,password } = req.body
const verify = await Users.findOne({where:{login: login}});
if(verify){ return res.status(400).json({result: 'User already exists'})}
const user = await Users.create({name,email,login,password});
}
model:
class Users extends Model {
static init(sequelize){
super.init({
name: DataTypes.STRING,
email: DataTypes.STRING,
login: DataTypes.STRING,
password: DataTypes.STRING,
}, {sequelize, tableName:'users'},
{
hooks: {
beforeCreate: (user) => {
console.log('ae');
},
},
}
)
do not enter my before and do not return my console.log
You should put the hooks option inside the second object parameter. Model.init() interface is:
public static init<M extends Model = Model>(this: ModelCtor<M>, attributes: ModelAttributes, options: InitOptions<M>): void;
Here is a working example:
import { sequelize } from '../../db';
import { Model, DataTypes } from 'sequelize';
class User extends Model {}
User.init(
{
name: DataTypes.STRING,
email: DataTypes.STRING,
login: DataTypes.STRING,
password: DataTypes.STRING,
},
{
sequelize,
tableName: 'users',
hooks: {
beforeCreate: (user) => {
console.log('======== ae ========');
},
},
},
);
(async function test() {
try {
await sequelize.sync({ force: true });
await User.create({ name: 'Alanna', email: 'example#gmail.com', login: 'value', password: '123' });
} catch (error) {
console.log(error);
} finally {
await sequelize.close();
}
})();
The execution results:
======== ae ========
Executing (default): INSERT INTO "users" ("id","name","email","login","password") VALUES (DEFAULT,$1,$2,$3,$4) RETURNING *;
Now, the beforeCreate hook of the User model works fine.
Related
I'm trying to understand how Sequelize works and I don't understand why I get SQLITE_ERROR: no such table: Users even though I created the table with sequelize.define. Code:
const { Sequelize, DataTypes } = require('sequelize');
const db = new Sequelize({
dialect: 'sqlite',
storage: './database.sqlite',
});
async function testdb() {
try {
await db.authenticate();
console.log('db connected'); // test 1
} catch (error) {
console.error(error);
}
const User = db.define('User', {
userName: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
email: {
type: DataTypes.STRING,
allowNull: false,
},
bio: {
type: DataTypes.TEXT,
},
});
console.log(db.models.User); // test 2
const user = await User.create({
userName: 'epic_user01',
email: 'epic.user#gmail.com',
bio: 'hello world!!!',
});
console.log(user.id); // test 3
}
testdb();
Tests 1 and 2 return successful before I get the error message.
You have to call sync to actually create the tables, add this right after the define and before the create:
await User.sync();
This is my node model using sequelize:
`
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class User extends Model {
static associate(models) {
User.hasMany(sequelize.models.Article, {
foreignKey: "posts",
});
}
}
User.init(
{
firstName: DataTypes.STRING,
lastName: DataTypes.STRING,
age: DataTypes.STRING,
email: DataTypes.STRING,
password: DataTypes.STRING,
type: DataTypes.STRING,
},
{
sequelize,
modelName: "User",
}
);
return User;
};
but this error, but I'm not able to use the module in other files, I want to use it in the Service, and I'm imposing it like this:
`
`const user = require("../models/user");
module.exports = {
async listUsers(req, res) {
const users = user.findAll();
await console.log(user);
res.send("okok");
// const users = await User;
// res.send(users);
},
}`
`
this error says: TypeError: user.findAll is not a function``
Prescso usar o model em outros arquivos, acredito que estou importando incorretamene por ser uma função
You've made a typo when calling the function.
It's not
user.findAll();
but
User.findAll();
That's how you have defined the model, also make sure the import has the right uppercase.
I wrote a class which extends a Model, and I need create a method to compareSync password:
const { Model, DataTypes } = require('sequelize');
class User extends Model {
static init(sequelize) {
super.init({
username: DataTypes.STRING,
password: DataTypes.STRING,
role: DataTypes.STRING,
status: DataTypes.INTEGER
},
{
sequelize,
hooks: {
beforeCreate: (user) => {
const salt = bcrypt.genSaltSync();
user.password = bcrypt.hashSync(user.password, salt);
}
}
}
)
}
static associate(model) {
this.belongsToMany(models.Movie, { through: models.Ratings });
}
}
module.exports = User;
The hook is working, I thought to add after beforeCreate a:
instanceMethods: {
validPassword: function (password) {
return bcrypt.compareSync(password, this.password);
}
}
Using this class how I can define an user method?
I got this:
const { Model, DataTypes } = require('sequelize');
const bcrypt = require("bcrypt")
class User extends Model {
static init(sequelize) {
super.init({
username: DataTypes.STRING,
password: DataTypes.STRING,
role: DataTypes.STRING,
status: DataTypes.INTEGER
},
{
sequelize,
hooks: {
beforeCreate: (user) => {
const salt = bcrypt.genSaltSync();
user.password = bcrypt.hashSync(user.password, salt);
}
}
}
)
}
static associate(model) {
this.belongsToMany(models.Movie, { through: models.Ratings });
}
validPassword(password) {
return bcrypt.compareSync(password, this.password);
}
}
module.exports = User;
If I wanna use the method inside controller for example:
const login = async (req, res) => {
const { username, password } = req.params;
const user = await User.findOne({
where: { username }
});
if (!user) {
return res.status(400).send("User not find!")
}
if(!user.validPassword(password)){..}
res.send(user)
}
I'm trying to learn Sequelize.js and I'm confused about its Many-To-Many Association.
What I've tried to do is simple Tasks Management with Users. Each task can be assignable to other users.
So, there's Users, Tasks and TaskContributors tables.
First, I made the POC version of my idea with Express.js. Then I found that I don't know how to insert to the Relational Table within different router.
Here are the model codes.
User Model
'use strict'
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define(
'User',
{
uid: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4 },
name: DataTypes.STRING,
password: DataTypes.STRING,
},
{},
)
User.associate = function (models) {
User.belongsToMany(models.Task, {
as: 'Contributors',
through: 'TaskContributors',
foreignKey: 'userId',
})
}
return User
}
Task Model
'use strict'
module.exports = (sequelize, DataTypes) => {
const Task = sequelize.define(
'Task',
{
uid: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4 },
name: DataTypes.STRING,
description: DataTypes.TEXT,
status: DataTypes.BOOLEAN,
},
{},
)
Task.associate = function (models) {
Task.belongsToMany(models.User, {
as: 'Task',
through: 'TaskContributors',
foreignKey: 'taskId',
})
}
return Task
}
TaskContributor Model
'use strict'
module.exports = (sequelize, DataTypes) => {
const TaskContributor = sequelize.define(
'TaskContributor',
{
userId: {
allowNull: false,
type: DataTypes.INTEGER,
references: { model: 'Users', key: 'id' },
},
taskId: {
allowNull: false,
type: DataTypes.INTEGER,
references: { model: 'Tasks', key: 'id' },
},
userStatus: { allowNull: false, type: DataTypes.STRING },
},
{},
)
TaskContributor.associate = function (models) {}
return TaskContributor
}
Routers
Users Router
router.get('/create/:name', (req, res) => {
User.create({ name: req.params.name, password: '123' })
.then((result) => res.send(result))
.catch((err) => res.status(500).send(err))
})
Tasks Router
router.get('/create/:userId/:name', (req, res) => {
const { userId, name } = req.params
User.findOne({ where: { uid: userId } }).then(async (user) => {
console.log(user)
const maybeTask = await user
.addTask({
name,
description: '',
status: false,
through: { userStatus: 'owner' },
})
.catch((err) => err)
if (maybeTask instanceof Error) res.status(500).send(maybeTask)
res.send(maybeTask)
})
})
When I tried to create new Task, it said user.addTask is not a function.
From what I understand from the Docs is that they showed how to create M-M association with two model.create() Objects, but not with the scenario like creating in different file.
I'm getting the error:
Unhandled rejection SequelizeDatabaseError: ER_LOCK_DEADLOCK: Deadlock found when trying to get lock; try restarting transaction
Here is my model:
var bcrypt = require('bcryptjs');
module.exports = function (sequelize, DataTypes) {
var User = sequelize.define('User', {
username: {type: DataTypes.STRING, unique: true},
password: DataTypes.STRING,
email: DataTypes.STRING,
isAdmin: DataTypes.BOOLEAN,
isActive: DataTypes.BOOLEAN
}, {
classMethods: {
associate: function (models) {
User.hasMany(models.Comment);
User.hasMany(models.Message, {as: 'receivedMessages', foreignKey: 'Receiver'});
User.hasMany(models.Message, {as: 'sentMessages', foreignKey: 'Sender'});
}
}
});
User.hook('beforeCreate', function (user, options, fn) {
bcrypt.genSalt(SALT_WORK_FACTOR, function (err, salt) {
if (err) {
return next(err);
}
bcrypt.hash(user.password, salt, function (err, hash) {
if (err) {
return next(err);
}
user.password = hash;
return fn(err, user);
});
});
});
User.findOrCreate({
where: {
username: 'admin'
},
defaults: {
username: 'admin',
email: 'admin#admin.com',
password: 'admin',
isAdmin: true,
isActive: true
}
});
return User;
};
If I remove one of the hooks (beforeCreate or findOrCreate), it works fine.
It seems to be an issue about transaction but I can't find a way to make it work.
The doc talks about passing the transaction but I don't know how to pass the transaction to findOrCreate.
Here is the doc: http://docs.sequelizejs.com/en/latest/docs/hooks/#model-hooks
Any idea? Thanks in advance!!
Not a solution but a workaround, instead of using the hook "findOrCreate", I've done it by my own:
User.find(
{
where: {
username: 'admin'
}
}
).then(function (user) {
if (!user) {
User.create({
username: 'admin',
email: 'admin#admin.com',
password: 'admin',
isAdmin: true,
isActive: true
}).then(function (newUser) {
console.log('Admin created with id: ' + newUser.id);
});
}
}
);
Maybe not the best answer but it works.
Can also be done with Promise.resolve
Promise.resolve(clientService.update(previousClient, { qa_inspection_template_id: null }, userId, transaction)).then(async ()=>
{
const client = await clientService.show(data.client_id, true);
await clientService.update(client, { qa_inspection_template_id: template.id }, userId, transaction);
});