'How to abort an update operation with beforeUpdate Hook Sequelize
How can i abort an update operation using beforeUpdate hook on sequelize and return a object as the result from a aborted update,
if i have something like:
User.beforeUpdate(function(user, options) {
if (user.name == "example_name") {
// abort operation here
// return object to the update caller
}
}
Solution 1:[1]
throw from before hooks does prevent the update
E.g.:
beforeUpdate: (integerName, options) => {
if (integerName.value === 5) {
throw new Error('beforeUpdate')
}
},
and throws on .update caller.
But remember from why sequelize beforeUpdate hook doesn't work? that the before only fires if the caller uses:
Model.update({}, {individualHooks: true})
which would be annoying to remember to pass every time.
The beforeValidate hook however fires even without individualHooks, so maybe that's the way to go.
The fact that throwing works for create is documented at: https://sequelize.org/master/manual/hooks.html#instance-hooks
User.beforeCreate(user => { if (user.accessLevel > 10 && user.username !== "Boss") { throw new Error("You can't grant this user an access level above 10!"); } });The following example will throw an error:
try { await User.create({ username: 'Not a Boss', accessLevel: 20 }); } catch (error) { console.log(error); // You can't grant this user an access level above 10! };The following example will be successful:
const user = await User.create({ username: 'Boss', accessLevel: 20 }); console.log(user); // user object with username 'Boss' and accessLevel of 20
Also mentioned at: https://github.com/sequelize/sequelize/issues/11298
Minimal runnable example:
main.js
#!/usr/bin/env node
const assert = require('assert')
const path = require('path')
const { DataTypes, Sequelize } = require('sequelize')
let sequelize
if (process.argv[2] === 'p') {
sequelize = new Sequelize('tmp', undefined, undefined, {
dialect: 'postgres',
host: '/var/run/postgresql',
})
} else {
sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.sqlite',
})
}
function assertEqual(rows, rowsExpect) {
assert.strictEqual(rows.length, rowsExpect.length)
for (let i = 0; i < rows.length; i++) {
let row = rows[i]
let rowExpect = rowsExpect[i]
for (let key in rowExpect) {
assert.strictEqual(row[key], rowExpect[key])
}
}
}
;(async () => {
const IntegerNames = sequelize.define('IntegerNames',
{
value: { type: DataTypes.INTEGER },
name: { type: DataTypes.STRING },
},
{
hooks: {
beforeCreate: (integerName, options) => {
if (integerName.value === 42) {
throw new Error('beforeCreate')
}
},
beforeValidate: (integerName, options) => {
if (integerName.value === 43) {
throw new Error('beforeValidate')
}
},
beforeUpdate: (integerName, options) => {
if (integerName.value === 5) {
throw new Error('beforeUpdate')
}
},
}
},
)
await IntegerNames.sync({ force: true })
async function reset() {
await sequelize.truncate({ cascade: true })
await IntegerNames.create({ value: 2, name: 'two' })
await IntegerNames.create({ value: 3, name: 'three' })
await IntegerNames.create({ value: 5, name: 'five' })
}
async function assertUnchanged() {
const rows = await IntegerNames.findAll()
assertEqual(rows, [
{ id: 1, value: 2, name: 'two', },
{ id: 2, value: 3, name: 'three', },
{ id: 3, value: 5, name: 'five', },
])
}
await reset()
let rows, exc
await assertUnchanged()
// beforeCreate
exc = undefined
try {
await IntegerNames.create({ value: 42, name: 'forty-two' })
} catch (e) {
exc = e
}
assert.strictEqual(exc.message, 'beforeCreate')
await assertUnchanged()
// beforeValidate
exc = undefined
try {
await IntegerNames.create({ value: 43, name: 'forty-three' })
} catch (e) {
exc = e
}
assert.strictEqual(exc.message, 'beforeValidate')
await assertUnchanged()
// beforeUpdate
exc = undefined
try {
await IntegerNames.update(
{ name: 'five hacked', },
{
where: { value: 5 },
individualHooks: true,
},
);
} catch (e) {
exc = e
}
assert.strictEqual(exc.message, 'beforeUpdate')
await assertUnchanged()
// using the beforeValidate
exc = undefined
try {
await IntegerNames.update(
{ value: 43, },
{
where: { value: 5 },
},
);
} catch (e) {
exc = e
}
assert.strictEqual(exc.message, 'beforeValidate')
await assertUnchanged()
})().finally(() => { return sequelize.close() })
package.json
{
"name": "tmp",
"private": true,
"version": "1.0.0",
"dependencies": {
"pg": "8.5.1",
"pg-hstore": "2.3.3",
"sequelize": "6.14.0",
"sql-formatter": "4.0.2",
"sqlite3": "5.0.2"
}
}
GitHub upstream. Tested on Ubuntu 21.10, PostgreSQL 13.5.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Ciro Santilli Путлер Капут å…四事 |
