Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I handle a Unique Field in sails?

I've defined a unique field in my model but when I tried to test it seems like it's not being checked by sails because I get a Error (E_UNKNOWN) :: Encountered an unexpected error: MongoError: E11000 duplicate key error index: instead a sails ValidationError.

What is the best way to handle a unique field in sails?

// model/User.js
module.exports{
attributes: {
  email: {required: true, unique: true, type: 'email' },
  ....
}
// in my controller
User.create({email: '[email protected]'}).then(...).fail(....)
User.create({email: '[email protected]'}).then(...).fail(// throws the mongo error ) 
// and same goes with update it throws error

Thanks in advance guys.

like image 799
ginad Avatar asked Apr 04 '14 16:04

ginad


2 Answers

The unique attribute currently only creates a unique index in MongoDB.

You may use the beforeValidate() callback to check for an existing record with that attribute and save the result in a class variable.

This approach makes sure that your model returns a proper validation error which can be evaluated by clients.

var uniqueEmail = false;

module.exports = {


    /**
     * Custom validation types
     */
    types: {
        uniqueEmail: function(value) {
            return uniqueEmail;
        }
    },

    /**
     * Model attributes
     */
    attributes: {
        email: {
            type: 'email',
            required: true,
            unique: true,            // Creates a unique index in MongoDB
            uniqueEmail: true        // Makes sure there is no existing record with this email in MongoDB
        }
    },

    /**
     * Lifecycle Callbacks
     */
    beforeValidate: function(values, cb) {
        User.findOne({email: values.email}).exec(function (err, record) {
            uniqueEmail = !err && !record;
            cb();
        });
    }
}

EDIT

As thinktt pointed out, there was an error in my former solution which rendered the default uniqueEmail value useless since it is defined within the model declaration itself and therefore cannot be referenced within the model code. I've edited my answer accordingly, thanks.

like image 146
tvollstaedt Avatar answered Nov 12 '22 06:11

tvollstaedt


You are trying to create two users with the same email address after defining the email as a unique field.

Maybe you can query for a user by that email address - if it exists already - return an error or update that user.

var params = {email: '[email protected]'};

User.findOne(params).done(function(error, user) {

  // DB error
  if (error) {
    return res.send(error, 500);
  }

  // Users exists
  if (user && user.length) {

    // Return validation error here
    return res.send({error: 'User with that email already exists'}, 403.9);
  }

  // User doesnt exist with that email
  User.create(params).done(function(error, user) {

    // DB error
    if (error) {
      return res.send(error, 500);
    }

    // New user creation was successful
    return res.json(user);

  });

});

Sails.js & MongoDB: duplicate key error index

There is also an interesting bit about unique model properties in the Sails.js docs https://github.com/balderdashy/waterline#indexing

EDIT: Pulled from http://sailsjs.org/#!documentation/models

Available validations are:

empty, required, notEmpty, undefined, string, alpha, numeric, alphanumeric, email, url, urlish, ip, ipv4, ipv6, creditcard, uuid, uuidv3, uuidv4, int, integer, number, finite, decimal, float, falsey, truthy, null, notNull, boolean, array, date, hexadecimal, hexColor, lowercase, uppercase, after, before, is, regex, not, notRegex, equals, contains, notContains, len, in, notIn, max, min, minLength, maxLength

like image 21
Chris McClellan Avatar answered Nov 12 '22 07:11

Chris McClellan