2013-05-03 1 views
2

Imaginez que je l'ai défini la fonction validateur personnalisé suivant:de validateur personnalisé, vérifiez le nom d'utilisateur uniques/mot de passe

isUnique: function() { // This works as expected 
    throw new Error({error:[{message:'Email address already in use!'}]}); 
} 

Cependant, lorsque je tente d'interroger la base de données que je rencontre des problèmes:

isUnique: function (email) { // This doesn't work 
    var User = seqeulize.import('/path/to/user/model'); 

    User.find({where:{email: email}}) 
    .success(function() { // This gets called 
     throw new Error({error:[{message:'Email address already in use!'}]}); // But this isn't triggering a validation error. 
    }); 
} 

Comment puis-je interroger l'ORM dans un validateur personnalisé et déclencher une erreur de validation en fonction de la réponse de l'ORM?

+0

bien que cela ne fonctionne pas, vous pouvez essayer de lancer '.find()' simple et en callback manipuler le résultat o f interrogez et appelez 'response.render' ou toute autre chose pour envoyer un message à l'utilisateur. – Gntem

+0

Sérieusement !? J'essaye de programmer à l'interface Sequelize plutôt qu'une implémentation solide. Pourquoi ce qui précède ne fonctionne pas? Je peux seulement imaginer que .find attrape l'erreur quelque part? –

+0

Juste pour clarifier, User.find ({where: {email: email}}). Success() fonctionne parfaitement (comme spécifié dans les docs Sequelize). Le problème est que Sequelize n'attrape pas l'erreur, ou que l'erreur est capturée ailleurs. –

Répondre

4

Le rappel de succès est appelé même si aucun utilisateur n'est trouvé. Vous devez vérifier si la fonction passe utilisateur comme argument:

isUnique: function (email) { // This doesn't work 
    var User = seqeulize.import('/path/to/user/model'); 

    User.find({where:{email: email}}) 
    .success(function (u) { // This gets called 
     if(u){ 
     throw new Error({error:[{message:'Email address already in use!'}]}); // But this isn't triggering a validation error. 
     } 
    }); 
} 
11

Voici un échantillon simplifié d'un rappel isUnique de validation qui fonctionne (fonctionne comme de SequelizeJS v2.0.0). J'ai ajouté des commentaires pour expliquer les bits importants:

var UserModel = sequelize.define('User', { 

    id: { 
     type: Sequelize.INTEGER(11).UNSIGNED, 
     autoIncrement: true, 
     primaryKey: true 
    }, 
    email: { 
     type: Sequelize.STRING, 
     validate: { 
      isUnique: function(value, next) { 

       UserModel.find({ 
        where: {email: value}, 
        attributes: ['id'] 
       }) 
        .done(function(error, user) { 

         if (error) 
          // Some unexpected error occured with the find method. 
          return next(error); 

         if (user) 
          // We found a user with this email address. 
          // Pass the error to the next method. 
          return next('Email address already in use!'); 

         // If we got this far, the email address hasn't been used yet. 
         // Call next with no arguments when validation is successful. 
         next(); 

        }); 

      } 
     } 
    } 

}); 

module.exports = UserModel; 
8

Avec Sequelize 2.0, vous devez détecter les erreurs de validation.

d'abord, définir le modèle de l'utilisateur avec un validateur personnalisé:

var User = sequelize.define('User', 
    { 
     email: { 
      type: Sequelize.STRING, 
      allowNull: false, 
      unique: true, 
      validate: { 
       isUnique: function (value, next) { 
        var self = this; 
        User.find({where: {email: value}}) 
         .then(function (user) { 
          // reject if a different user wants to use the same email 
          if (user && self.id !== user.id) { 
           return next('Email already in use!'); 
          } 
          return next(); 
         }) 
         .catch(function (err) { 
          return next(err); 
         }); 
       } 
      } 
     }, 
     other_field: Sequelize.STRING 
    }); 

module.exports = User; 

Ensuite, dans le contrôleur, attraper les erreurs de validation:

var Sequelize = require('sequelize'), 
    _ = require('lodash'), 
    User = require('./path/to/User.model'); 

exports.create = function (req, res) { 
    var allowedKeys = ['email', 'other_field']; 
    var attributes = _.pick(req.body, allowedKeys); 
    User.create(attributes) 
     .then(function (user) { 
      res.json(user); 
     }) 
     .catch(Sequelize.ValidationError, function (err) { 
      // respond with validation errors 
      return res.status(422).send(err.errors); 
     }) 
     .catch(function (err) { 
      // every other error 
      return res.status(400).send({ 
       message: err.message 
      }); 
     }); 
8

Vous pouvez vérifier si l'e-mail existe déjà comme ça :

email: { 
    type: Sequelize.STRING, 
    allowNull: false, 
    validate: { 
    isEmail:true 
    }, 
    unique: { 
     args: true, 
     msg: 'Email address already in use!' 
    } 
} 
+3

Ceci! Je ne comprends pas pourquoi les autres doivent lancer un 'user.find' avant l'insertion. – BaNz

+0

@BaNz oui vous pouvez le faire et évidemment c'est mieux, mais si vous avez une valeur d'incrémentation automatique dans la table, si votre requête d'insertion échoue en raison d'une violation unique, votre ID augmente automatiquement. –

Questions connexes