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

Commit d5b08b4f by Bart Nagel

Add model validations option

The existing but unused (as far as I could tell) DAO option `validate`
can now have member methods which will be called with the model object's
context after the other (field-specific) validations.

Only custom functions are allowed (since isInt etc wouldn't make sense
in this context).

As with other custom validations, they are deemed to pass if they throw
no error, or fail if an error is thrown.

Any error messages collected are added to a '_' member array of the
validation result object, alongside the arrays named after any fields
whose validations failed.

Example:

	var Pub = Sequelize.define('Pub', {
		name: { type: Sequelize.STRING },
		address: { type: Sequelize.STRING },
		latitude: {
			type: Sequelize.INTEGER,
			allowNull: true,
			defaultValue: null,
			validate: { min: -90, max: 90 }
		},
		longitude: {
			type: Sequelize.INTEGER,
			allowNull: true,
			defaultValue: null,
			validate: { min: -180, max: 180 }
		},
	}, {
		validate: {
			xorCoords: function() {
				if ((this.latitude === null) === (this.longitude === null)) {
					throw new Error('Require either both latitude and longitude or neither')
				}
			}
		}
	})

In this simple case an object fails validation if latitude or longitude
is given, but not both. If we try to build one with an out of range
latitude and no longitude, `raging_bullock_arms.validate()`, might
return

	{
		'latitude': ['Invalid number: latitude'],
		'_': ['Require either both latitude and longitude or neither']
	}

A test is included.
1 parent 41c1b6ae
......@@ -30,9 +30,6 @@ module.exports = (function() {
this.rawAttributes = attributes
this.daoFactoryManager = null // defined in init function
this.associations = {}
// extract validation
this.validate = this.options.validate || {}
}
Object.defineProperty(DAOFactory.prototype, 'attributes', {
......
......@@ -269,6 +269,20 @@ module.exports = (function() {
} // if field has validator set
}) // for each field
// for each model validator for this DAO
Utils._.each(self.__options.validate, function(validator, validatorType) {
if (!Utils._.isFunction(validator))
throw new Error("Invalid model validator function: " + validatorType);
try {
validator.apply(self)
} catch (err) {
if (!failures.hasOwnProperty('_')) {
failures._ = []
}
failures._.push(err.message)
}
})
return (Utils._.isEmpty(failures) ? null : failures)
}
......
......@@ -306,5 +306,34 @@ describe(Helpers.getTestDialectTeaser("DAO"), function() {
var successfulUser2 = User.build({ age: 1 })
expect(successfulUser2.validate()).toBeNull()
})
it('validates a model with custom model-wide validation methods', function() {
var Foo = this.sequelize.define('Foo' + Math.random(), {
field1: {
type: Sequelize.INTEGER,
allowNull: true
},
field2: {
type: Sequelize.INTEGER,
allowNull: true
}
}, {
validate: {
xor: function() {
if ((this.field1 === null) === (this.field2 === null)) {
throw new Error('xor failed');
}
}
}
})
var failingFoo = Foo.build({ field1: null, field2: null })
, errors = failingFoo.validate()
expect(errors).not.toBeNull()
expect(errors).toEqual({ '_': ['xor failed'] })
var successfulFoo = Foo.build({ field1: 33, field2: null })
expect(successfulFoo.validate()).toBeNull()
})
})
})
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!