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

Commit 2e96f20e by Sascha Depold

splitted validation logic into multiple parts

1 parent 3a519205
Showing with 103 additions and 61 deletions
...@@ -6,72 +6,113 @@ var DaoValidator = module.exports = function(model) { ...@@ -6,72 +6,113 @@ var DaoValidator = module.exports = function(model) {
} }
DaoValidator.prototype.validate = function() { DaoValidator.prototype.validate = function() {
var self = this.model var errors = {}
var failures = {}
// for each field and value errors = Utils._.extend(errors, validateAttributes.call(this))
Utils._.each(self.values, function(value, field) { errors = Utils._.extend(errors, validateModel.call(this))
// if field has validators return errors
var hasAllowedNull = (self.rawAttributes[field].allowNull && self.rawAttributes[field].allowNull === true && (value === null || value === undefined)); }
if (self.validators.hasOwnProperty(field) && !hasAllowedNull) { // private
// for each validator
Utils._.each(self.validators[field], function(details, validatorType) { var validateModel = function() {
var errors = {}
var is_custom_fn = false // if true then it's a custom validation method
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 : details
if (!Array.isArray(fn_args))
fn_args = [fn_args]
// error msg
fn_msg = details.hasOwnProperty("msg") ? details.msg : false
// check method exists
var v = Validator.check(value, fn_msg)
if (!Utils._.isFunction(v[validatorType]))
throw new Error("Invalid validator function: " + validatorType)
// bind to validator obj
fn_method = Utils._.bind(v[validatorType], v)
}
try {
fn_method.apply(null, fn_args)
} catch (err) {
err = err.message
// if we didn't provide a custom error message then augment the default one returned by the validator
if (!fn_msg && !is_custom_fn)
err += ": " + field
// each field can have multiple validation failures stored against it
if (failures.hasOwnProperty(field)) {
failures[field].push(err)
} else {
failures[field] = [err]
}
}
}) // for each validator for this field
} // if field has validator set
}) // for each field
// for each model validator for this DAO // for each model validator for this DAO
Utils._.each(self.__options.validate, function(validator, validatorType) { Utils._.each(this.model.__options.validate, function(validator, validatorType) {
try { try {
validator.apply(self) validator.apply(this.model)
} catch (err) { } catch (err) {
failures[validatorType] = [err.message] // TODO: data structure needs to change for 2.0 errors[validatorType] = [err.message] // TODO: data structure needs to change for 2.0
}
}.bind(this))
return errors
}
var validateAttributes = function() {
var errors = {}
// for each field and value
Utils._.each(this.model.values, function(value, field) {
var rawAttribute = this.model.rawAttributes[field]
, hasAllowedNull = ((rawAttribute.allowNull === true) && ((value === null) || (value === undefined)))
if (this.model.validators.hasOwnProperty(field) && !hasAllowedNull) {
errors = Utils._.merge(errors, validateAttribute.call(this, value, field))
} }
}) }.bind(this)) // for each field
return failures return errors
} }
var validateAttribute = function(value, field) {
var errors = {}
// for each validator
Utils._.each(this.model.validators[field], function(details, validatorType) {
var validator = prepareValidationOfAttribute.call(this, value, details, validatorType)
try {
validator.fn.apply(null, validator.args)
} catch (err) {
var msg = err.message
// if we didn't provide a custom error message then augment the default one returned by the validator
if (!validator.msg && !validator.isCustom) {
msg += ": " + field
}
// each field can have multiple validation errors stored against it
errors[field] = errors[field] || []
errors[field].push(msg)
}
}.bind(this)) // for each validator for this field
return errors
}
var prepareValidationOfAttribute = function(value, details, validatorType) {
var isCustomValidator = false // if true then it's a custom validation method
, validatorFunction = null // the validation function to call
, validatorArgs = [] // extra arguments to pass to validation function
, errorMessage = "" // the error message to return if validation fails
if (typeof details === 'function') {
// it is a custom validator function?
isCustomValidator = true
validatorFunction = Utils._.bind(details, this.model, value)
} else {
// it is a validator module function?
// extract extra arguments for the validator
validatorArgs = details.hasOwnProperty("args") ? details.args : details
if (!Array.isArray(validatorArgs)) {
validatorArgs = [validatorArgs]
}
// extract the error msg
errorMessage = details.hasOwnProperty("msg") ? details.msg : false
// check method exists
var validator = Validator.check(value, errorMessage)
// check if Validator knows that kind of validation test
if (!Utils._.isFunction(validator[validatorType])) {
throw new Error("Invalid validator function: " + validatorType)
}
// bind to validator obj
validatorFunction = Utils._.bind(validator[validatorType], validator)
}
return {
fn: validatorFunction,
msg: errorMessage,
args: validatorArgs,
isCustom: isCustomValidator
}
}
...@@ -329,6 +329,7 @@ describe(Helpers.getTestDialectTeaser("DaoValidator"), function() { ...@@ -329,6 +329,7 @@ describe(Helpers.getTestDialectTeaser("DaoValidator"), function() {
var failingFoo = Foo.build({ field1: null, field2: null }) var failingFoo = Foo.build({ field1: null, field2: null })
, errors = failingFoo.validate() , errors = failingFoo.validate()
expect(errors).not.toBeNull() expect(errors).not.toBeNull()
expect(errors).toEqual({ 'xnor': ['xnor failed'] }) expect(errors).toEqual({ 'xnor': ['xnor failed'] })
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!