sequelize/sequelize — pull request #1476 by thanpolas (2014-03-07 13:03:51+00:00)
Title: Refactor dao validator

Ok, this is a complete rewrite of the DAO-Validator, goals achieved:

* Lowered complexity, code is more readable and easy to understand now
* Did not change how API works, some very subtle changes were made that need to be discussed (more bellow)
* All validation checks are passed and all errors reported (vs stopping at first error)
* Custom validators can now also accept a promise as a returned value to trigger asynchronicity

There was a division of validators, here's the new taxonomy (language) so we can all have a good idea of what's going on:

1. **Built-in Validators** (also described as per attribute validators)
1. **Attribute Custom Validator** One can define a custom validator inside an attribute
1. **Custom Validators** (also described as Model validators)

### Changes

#### Master Error Container

The master error container used to be an instance of Error, i changed that to be an Object Literal, the reason was that there were some nasty namespace collisions that generated `Illegal Access` errors out of the blue, the issue manifested when attribute names collided with properties of the Error object (i.e. `name`). Thus the tests were slightly changed to acomodate that.

#### Attribute Custom Validators

An Attribute Custom Validator will now produce an instance of Error vs `string`. Thus the error message can be accessed using `error.message`. If `error` is used as is, it's internal method `toString()` will invoked which will result in the message with this string prepended `Error: `, which is not that must a breaking change. Tests have been adjusted to this change.

There's a slight inconsistency introduced with this change, Built-in validators will generate a string, so one could possibly have two kinds of Objects in the error Object. Consider this case:

```js
var Model = this.sequelize.define('model', {
name: {
type: Sequelize.STRING,
validate: {
notNull: true, // won't allow null
custom: function(val) {
throw new Error('custom error');
}
}
}
})
```

When this model tries to create an item with the `name` attribute as null, the error Object will look like this:

```js
error = {
name:[
'Validation notNull failed',
Error(),
]
}
```

The second array item comes from the custom validator... Since [we discussed the benefits of an Error Object vs Strings](https://github.com/sequelize/sequelize/pull/1360), my suggestion would be to switch built-in validators to generate Error Objects too.