Валидатор Sequelize возвращает только одну ошибку за раз

После создания или обновления элементов в моей базе данных с помощью 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' } ...

Остальную часть я обрезал, но, как видите, она возвращает ошибку только для имени пользователя. Когда я исправляю это, а затем снова отправляю свою форму, только тогда я получаю сообщение об ошибке проверки адреса электронной почты.

У меня такая же проблема, вы ее решили?

rojcyk 05.08.2018 15:53

Мне также любопытно, было ли это когда-либо решено. Этот ответ использует настраиваемые функции проверки isUnique, которые вызывают метод find / findOne как для имени пользователя, так и для адреса электронной почты. Нельзя этого добиться без использования метода findOne? Мне нужны все ошибки, а не одна ошибка.

cocomatt 18.03.2020 20:07
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
2
1 319
1

Ответы 1

Я была такая же проблема.

Если у вас установлено ограничение allowNull:false для свойства и ваше поле для этого свойства имеет значение null, все валидаторы будут пропущены, и будет выдана ошибка ValidationError. Таким образом, ограничения db проверяются сначала, одно за другим, после чего выполняется обычная проверка, при которой все ошибки возвращаются в массив, как и ожидалось.

Здесь - ссылка на вышеупомянутый

У меня такая же проблема, и моя проблема не в этом. У меня есть 2 поля (имя пользователя и адрес электронной почты), которые имеют ненулевые и уникальные ограничения, и я передаю ненулевые значения для обоих при попытке создания и экземпляра модели, и я получаю только первую ошибку проверки. Как упоминалось в OP, если я исправлю эту ошибку, изменив ее на неиспользуемое значение, будет возвращена следующая ошибка проверки.

az2tonez 31.01.2020 06:15

Оказывается, в моем случае проблема заключалась в неправильном понимании различия между валидатором и ограничением и ожидании того, что ограничения будут вести себя как валидаторы (то есть возвращать несколько сбоев уникальных ограничений, в данном случае в виде одной выданной ошибки). Для всех, кто запутался в этой терминологии, достаточно простой способ запомнить разницу в том, что валидаторы работают ДО того, как любой SQL будет выполнен для БД. Ограничения (уникальные, ненулевые и т. д.) В значительной степени соответствуют их фактическим представлениям в БД.

az2tonez 31.01.2020 06:48

Вот документация, которая вызвала вышеупомянутое "AHA!" момент для меня: ссылка на сайт

az2tonez 31.01.2020 06:49

Другие вопросы по теме