После создания или обновления элементов в моей базе данных с помощью Sequelize я обнаружил, что валидатор возвращает только одну ошибку валидации за раз.
Это не идеально, поскольку я хотел бы возвращать все ошибки пользователю, когда он отправляет форму, в которой есть несколько ошибок.
Это моя модель:
module.exports = (Sequelize, DataTypes) => {
const User = Sequelize.define(
'user',
{
email: {
type: DataTypes.STRING,
allowNull: false,
unique: {
args: true,
msg: 'That email is not available.'
},
validate: {
isEmail: {
args: true,
msg: 'Please enter a valid email.'
}
}
},
username: {
type: DataTypes.STRING,
allowNull: false,
notEmpty: true,
unique: {
args: true,
msg: 'That username is not available.'
},
validate: {
min: {
args: USER_USERNAME_MIN_LENGTH,
msg: 'Please choose a longer username.'
},
max: {
args: USER_USERNAME_MAX_LENGTH,
msg: 'Please choose a shorter username.'
},
is: {
args: /^[0-9a-zA-Z](/?[a-zA-Z0-9-_])*/?$/i,
msg: 'Please enter a valid username.'
}
}
}
},
{
underscored: true,
}
);
return User;
};
Это мой контроллер (в данном случае я пытаюсь обновить пользователя, скажем, User 1, и изменить их значения для username и email, которые, как оказалось, совпадают с точными значениями для другого пользователя, скажем, User 2).
try {
const user = await User.findById(req.user.id);
if (user) {
const updatedUser = await user.update({
username: username || req.user.username,
email: email || req.user.email
});
res.status(200).end();
}
} catch (err) {
console.info(err);
return res.status(500).send(getMappedErrors(err));
}
Таким образом, можно ожидать, что валидатор вернет ошибки как для поля email, так и для поля username, поскольку он нарушает флаг unique.
Однако вот что я получаю в этом блоке catch:
{ SequelizeUniqueConstraintError: That username is not available.
at Query.formatError (/site/node_modules/sequelize/lib/dialects/postgres/query.js:325:18)
at query.catch.err (/site/node_modules/sequelize/lib/dialects/postgres/query.js:86:18)
at tryCatcher (/site/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/site/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (/site/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (/site/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/site/node_modules/bluebird/js/release/promise.js:689:18)
at Async._drainQueue (/site/node_modules/bluebird/js/release/async.js:133:16)
at Async._drainQueues (/site/node_modules/bluebird/js/release/async.js:143:10)
at Immediate.Async.drainQueues [as _onImmediate] (/site/node_modules/bluebird/js/release/async.js:17:14)
at runCallback (timers.js:763:18)
at tryOnImmediate (timers.js:734:5)
at processImmediate (timers.js:716:5)
at process.topLevelDomainCallback (domain.js:101:23)
name: 'SequelizeUniqueConstraintError',
errors:
[ ValidationErrorItem {
message: 'That username is not available.',
type: 'unique violation',
path: 'username',
value: 'bob',
origin: 'DB',
instance: [user],
validatorKey: 'not_unique',
validatorName: null,
validatorArgs: [] } ],
fields: { username: 'bob' },
parent:
{ error: duplicate key value violates unique constraint "users_username_key"
at Connection.parseE (/site/node_modules/pg/lib/connection.js:545:11)
at Connection.parseMessage (/site/node_modules/pg/lib/connection.js:370:19)
at Socket.<anonymous> (/site/node_modules/pg/lib/connection.js:113:22)
at Socket.emit (events.js:127:13)
at Socket.emit (domain.js:421:20)
at addChunk (_stream_readable.js:269:12)
at readableAddChunk (_stream_readable.js:256:11)
at Socket.Readable.push (_stream_readable.js:213:10)
at TCP.onread (net.js:598:20)
name: 'error',
length: 204,
severity: 'ERROR',
code: '23505',
detail: 'Key (username)=(bob) already exists.',
hint: undefined,
position: undefined,
internalPosition: undefined,
internalQuery: undefined,
where: undefined,
schema: 'public',
table: 'users',
column: undefined,
dataType: undefined,
constraint: 'users_username_key',
file: 'nbtinsert.c',
line: '434',
routine: '_bt_check_unique',
sql: 'UPDATE "users" SET "username"=\'bob\',"email"=\'[email protected]\',"updated_at"=\'2018-03-28 19:26:27.341 +00:00\' WHERE "id" = 2' } ...
Остальную часть я обрезал, но, как видите, она возвращает ошибку только для имени пользователя. Когда я исправляю это, а затем снова отправляю свою форму, только тогда я получаю сообщение об ошибке проверки адреса электронной почты.
Мне также любопытно, было ли это когда-либо решено. Этот ответ использует настраиваемые функции проверки isUnique, которые вызывают метод find / findOne как для имени пользователя, так и для адреса электронной почты. Нельзя этого добиться без использования метода findOne? Мне нужны все ошибки, а не одна ошибка.





Я была такая же проблема.
Если у вас установлено ограничение allowNull:false для свойства и ваше поле для этого свойства имеет значение null, все валидаторы будут пропущены, и будет выдана ошибка ValidationError. Таким образом, ограничения db проверяются сначала, одно за другим, после чего выполняется обычная проверка, при которой все ошибки возвращаются в массив, как и ожидалось.
Здесь - ссылка на вышеупомянутый
У меня такая же проблема, и моя проблема не в этом. У меня есть 2 поля (имя пользователя и адрес электронной почты), которые имеют ненулевые и уникальные ограничения, и я передаю ненулевые значения для обоих при попытке создания и экземпляра модели, и я получаю только первую ошибку проверки. Как упоминалось в OP, если я исправлю эту ошибку, изменив ее на неиспользуемое значение, будет возвращена следующая ошибка проверки.
Оказывается, в моем случае проблема заключалась в неправильном понимании различия между валидатором и ограничением и ожидании того, что ограничения будут вести себя как валидаторы (то есть возвращать несколько сбоев уникальных ограничений, в данном случае в виде одной выданной ошибки). Для всех, кто запутался в этой терминологии, достаточно простой способ запомнить разницу в том, что валидаторы работают ДО того, как любой SQL будет выполнен для БД. Ограничения (уникальные, ненулевые и т. д.) В значительной степени соответствуют их фактическим представлениям в БД.
Вот документация, которая вызвала вышеупомянутое "AHA!" момент для меня: ссылка на сайт
У меня такая же проблема, вы ее решили?