Bookshelf.js在创建新记录之前进行唯一的电子邮件验证

时间:2016-07-01 14:44:27

标签: node.js validation express bookshelf.js joi

创建新记录时,我在Bookshelf.js尝试验证电子邮件已存在验证。

我在这里找到了一个解决方案github,但它无效,即使我尝试使用Promise

User = bookshelf.Model.extend({
  tableName: 'users',
  initialize: function() {
    this.on('saving', this._assertEmailUnique);
  },
  _assertEmailUnique: function(model, attributes, options) {
    if (this.hasChanged('email')) {
      return this
        .query('where', 'email', this.get('email'))
        .fetch(_.pick(options, 'transacting'))
        .then(function (existing) {
          if (!existing) throw new Error('duplicate email');
        });
    }
  }
});

对于目前使用Joi的模型验证,看起来Joi也不支持自定义验证。我正在使用Postgres数据库。还有其他方法可以做..请帮忙......

提前致谢..

2 个答案:

答案 0 :(得分:2)

您的代码有两个错误阻止它工作:

  1. if (!existing) ...应该被颠倒,因为如果给定的电子邮件已经存在,您想要失败
  2. 查询this会将您的查询限制为当前记录,您需要使用普通User
  3. 从头开始查询

    使用这些修补程序,您的代码将如下所示:

    User = bookshelf.Model.extend({
      tableName: 'users',
      initialize: function() {
        this.on('saving', this._assertEmailUnique);
      },
      _assertEmailUnique: function(model, attributes, options) {
        if (this.hasChanged('email')) {
          return User
            .query('where', 'email', this.get('email'))
            .fetch(_.pick(options || {}, 'transacting'))
            .then(function(existing) {
              if (existing) {
                throw new Error('Duplicated email: User id #' + existing.id);
              }
            });
        }
      }
    });
    

答案 1 :(得分:1)

email列上设置唯一的键约束,然后在模型内,在违反该约束时进行捕获,这是更有效的

例如 在您的数据库迁移方面做类似的事情

...
table.string('email').notNullable().unique();

然后重写模型的save方法,并从那里抛出应用程序特定的错误,如下所示:

User = bookshelf.Model.extend({
  tableName: 'users',
  save: function () {
        return bookshelf.Model.prototype.save.apply(this, arguments)
        .catch((error) => {
            if (error.code === '23505') { //unique_violation code if using postgres db
                throw new errors.DuplicateUserEmail('User with the same email already exists');
            }

            throw error;
        });
    }
});