Matt Fletcher
Matt Fletcher

Reputation: 9220

Fire Mongoose validation failure in model presave

I would like to create a validator for Mongoose that causes .save() to fail if the row already exists. At the moment my validators look somewhat like this (coffee):

model.schema.path('email').validate (email) =>
  return email? and email.length > 0
, 'BLANK_EMAIL'

However, they are synchronous and therefore having a @model.find checking for length inside there would not work. I was considering using something like the pseudo-code below but I don't know if it's possible, or if there's a much easier method that will follow the same mongoose validation pattern I'm already using. Thanks!

model.schema.pre 'save', (next) ->
  self = @
  model.find {email: self.email}, (err, rows) ->
    if rows.length
      # This bit is the pseudo-code:
      model.schema.path('email').validate false
    next()

Upvotes: 0

Views: 101

Answers (1)

RickN
RickN

Reputation: 13500

http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate

schema.path('email').validate(function (value, respond) {
  mongoose.model("user").count({email: this.email}, function(err, num) {
    respond(!(err || num)); // validation failed
  })
 }, '{PATH} failed validation.');

You might want to check for email: this.email, _id: {$ne: this._id}, depending on your needs. The above snippet is untested, but you get the general idea.

Validators with two arguments (value & a callback) run asynchronously, as opposed to validators with a single argument (value), which must return a boolean. The callback receives a boolean which indicates that the error should be thrown. AFAIK, you can't pass an Error instance to the callback.

Upvotes: 1

Related Questions