不要怂,就是干,撸起袖子干!

Commit 56237112 by Ram

Added ability to supply custom validation methods. Each custom validation method…

… recieves the field value to validate as its sole argument. It should throw an error to indicate a validation failure. For example:

<pre>
      User = sequelize.define('User', {
        name: {
          type: Sequelize.STRING,
          validate: {
              len: {
                args: 9,
		msg: "Need atleast 9 chars"
              },
              customFn1: function(val) {
                # if name doesn't start with 'joe' then fail
                if (val.substr(0,3) !== "joe")
                    throw new Error("name should start with 'joe'")
              },
              customFn2: function(val) {
                # if name doesn't end in 'bloggs' then fail
                if (val.substr(-6) !== "bloggs")
                    throw new Error("name should end with 'bloggs'")
              }
          }
        }
      });
</pre>

You still invoke validation as you normally would, i.e.:

<pre>
# build user
var user = User.build({
    name : "test"
});

# validate
errors = user.validate();
# At this point errors will contain:
#
# { name : [
#	"Need atleast 9 chars"
#	"name should start with 'joe'"
#	"name should end with 'bloggs'"
# ] }
#
</pre>
1 parent 6ae3b957
Showing with 60 additions and 14 deletions
...@@ -65,24 +65,38 @@ module.exports = (function() { ...@@ -65,24 +65,38 @@ module.exports = (function() {
// for each validator // for each validator
Utils._.each(self.validators[field], function(details, validatorType) { Utils._.each(self.validators[field], function(details, validatorType) {
// validator arguments var is_custom_fn = false // if true then it's a custom validation method
var fn_args = details.hasOwnProperty("args") ? details.args : [] var fn_method = null // the validation function to call
var fn_args = [] // extra arguments to pass to validation function
var fn_msg = "" // the error message to return if validation fails
// is it a custom validator function?
if (Utils._.isFunction(details)) {
is_custom_fn = true
fn_method = Utils._.bind(details, self, value)
}
// is it a validator module function?
else {
// extra args
fn_args = details.hasOwnProperty("args") ? details.args : []
if (!Utils._.isArray(fn_args)) if (!Utils._.isArray(fn_args))
fn_args = [fn_args] fn_args = [fn_args]
// error msg // error msg
var fn_msg = details.hasOwnProperty("msg") ? details.msg : false fn_msg = details.hasOwnProperty("msg") ? details.msg : false
// check method exists
var validator = Validator.check(value, fn_msg) var v = Validator.check(value, fn_msg)
if (!Utils._.isFunction(v[validatorType]))
if (!Utils._.isFunction(validator[validatorType]))
throw new Error("Invalid validator function: " + validatorType) throw new Error("Invalid validator function: " + validatorType)
// bind to validator obj
fn_method = Utils._.bind(v[validatorType], v)
}
try { try {
validator[validatorType].apply(validator, fn_args) fn_method.apply(null, fn_args)
} catch (err) { } catch (err) {
err = err.message err = err.message
// if we didn't provide a custom error message then augment the default one returned by the validator // if we didn't provide a custom error message then augment the default one returned by the validator
if (!fn_msg) if (!fn_msg && !is_custom_fn)
err += ": " + field err += ": " + field
// each field can have multiple validation failures stored against it // each field can have multiple validation failures stored against it
if (failures.hasOwnProperty(field)) { if (failures.hasOwnProperty(field)) {
......
...@@ -72,8 +72,7 @@ describe('Model', function() { ...@@ -72,8 +72,7 @@ describe('Model', function() {
}) })
}) })
describe('Model', function() { describe('Validations', function() {
describe('Validations', function() {
var checks = { var checks = {
is : { is : {
spec : { args: [/[a-z]/,'i'] }, spec : { args: [/[a-z]/,'i'] },
...@@ -223,7 +222,7 @@ describe('Model', function() { ...@@ -223,7 +222,7 @@ describe('Model', function() {
var User, i; var User, i;
it('should correctly validate according to supplied rules', function() { it('should correctly validate using node-validator methods', function() {
Helpers.async(function(done) { Helpers.async(function(done) {
for (var validator in checks) { for (var validator in checks) {
if (checks.hasOwnProperty(validator)) { if (checks.hasOwnProperty(validator)) {
...@@ -283,6 +282,39 @@ describe('Model', function() { ...@@ -283,6 +282,39 @@ describe('Model', function() {
done(); done();
}); });
}); });
})
}); it('should correctly validate using custom validation methods', function() {
Helpers.async(function(done) {
User = sequelize.define('User' + Math.random(), {
name: {
type: Sequelize.STRING,
validate: {
customFn: function(val) {
if (val !== "2")
throw new Error("name should equal '2'")
}
}
}
});
var u_fail = User.build({
name : "3"
});
var errors = u_fail.validate();
expect(errors).toNotBe(null);
expect(errors).toEqual({
name : ["name should equal '2'"]
});
var u_success = User.build({
name : "2"
});
expect(u_success.validate()).toBe(null);
done();
});
});
})
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!