Skip to content
danschultz edited this page Jan 20, 2011 · 1 revision

Validations represent an essential paradigm in ensuring that only valid data is sent to your server. For instance, it might be important for your application to ensure that every user has a name and a valid email address. These validations are defined on your entity and are automatically triggered before a save operation.

Defining validations on your model keeps your validation logic DRY by defining them in one place. These validations can not only be used by Mesh, but can also be reused by your views for presenting feedback to users on invalid data entry.

1. Defining Validations

Validations are defined in your entity classes by specifying a public static object variable named validate. This object contains key-value pairs where the key represents the property to validate, and the value is an array of validations for that property.

public dynamic class Person extends Entity
{
	public static var validate:Object = {
		name: [{validator: PresenceOf, message: "Missing a name."}],
		age: [{validator: Numeric, greaterThan: 0}]
	};
	
	[Bindable] public var name:String;
	[Bindable] public var age:Number;
}

Entities inherit validations from their parent. So if Customer extends from Person, then Customer will also run the validations defined on Person.

public dynamic class Customer extends Person
{
	public static var validate:Object = {
		accountNumber: [{validator: PresenceOf}]
	};
	
	[Bindable] public var accountNumber:String;
}

2. Running Validations

By default, any call to save() will also invoke the validations defined for that entity. You can bypass this functionality by passing false to save().

person.save(); // run validations before the save operation executes.
person.save(false); // skip validations

2.1. isValid() and isInvalid()

To verify if an entity is valid, Mesh invokes the entity's isValid() method. You may also use this method on your own. This method triggers the entity's validations to be run, and returns true if no errors were added to the object.

person.name = "John";
person.isValid(); // true;
person.isInvalid(); // false;

person.name = "";
person.isValid(); // false;
person.isInvalid(); // true;

isInvalid() is simply the inverse of valid(). Running this method will trigger the entity's validations and return true if any errors were added.

3. Errors

An entity defines an errors property which is an object of key-value pairs that were added from the validation. The key represents the property that has an error, and its value is an array of strings for each error message. If an entity is valid, then its errors property is empty.

3.1. errors[]

You can use the errors[] accessor for getting the error messages for a certain property. This returns an array of strings for all the error messages on that property.

public dynamic class Person extends Entity
{
	public static var validate:Object = {
		name: [{validator: PresenceOf, message: "Missing a name."}, {validator: Length, minimum: 2}]
	};
	
	[Bindable] public var name:String;
}

person.isValid();
trace(person.errors["name"]); // ["can't be empty", "is too short"]

3.2. Iterating Through Errors

To iterate through the errors, you can run a for each..in loop on the errors property. Each error string in the iteration will also contain the property's name in a human readable format.

person.firstName = "";
person.lastName = "";
person.isValid();

for each (var error:String in person.errors) {
	trace(error);
}
// traces: 
// "first name can't be empty"
// "last name can't be empty"

You may also call the errors.forEach method, which expects a block function that takes in two arguments, property:String and error:String.

person.firstName = "";
person.lastName = "";
person.isValid();

person.errors.forEach(function(property:String, error:String):void
{
	// do something
});

4. Types of Validations

Mesh includes a set of common validations for you to use:

  • NumericValidator
  • LengthValidator
  • FormatValidator
  • PresenceValidator
  • InclusionValidator
  • ExclusionValidator

4.1. NumericValidator

This validator tests if a property is a number, and whether or not that number is a certain value.

If the integer option is set to true, then it will attempt to validate the number using the following regular expression:

/\A[+-]?\d+\Z/

Available options:

  • integer: boolean. Message: "is not a number"
  • even: boolean. Message: "must be even"
  • odd: boolean. Message: "must be odd"
  • greaterThan: number. Message: "must be greater than {count}"
  • greaterThanOrEqualTo: number. Message: "must be greater than or equal to {count}"
  • equalTo: number. Message: "must be equal to {count}"
  • lessThan: number. Message: "must be less than {count}"
  • lessThanOrEqualTo: number. Message: "must be less than or equal to {count}"

4.2. LengthValidator

The length validator tests if a property is of a certain length. This validator can check any object that contains a length property, such as a String or an Array.

Available options:

  • exactly: uint. The properties length must be exactly n.
  • minimum: uint. The properties length must be no less than n.
  • maximum: uint. The properties length must be no greater than n.
  • between: string, i.e. "1..5". The properties length must be at least 1 and no more than 5.

You can customize the messages by specifying the tooShort, tooLong and wrongLength options with a string. You may also include {count} which will be replaced with the constraint. For example:

public dynamic class Person extends Entity
{
	public static var validate:Object = {
		name: [{validator: LengthValidator, minimum: 2, tooShort: "{count} is the minimum number of characters"}]
	};
}

4.3. FormatValidator

This validator tests a string against a regular expression.

Available options:

  • format: RegExp. The regular expression to test against.
  • message: String. A custom error message. Defaults to "is invalid".

This format validation tests that the property only contains letters:

public dynamic class Person extends Entity
{
	public static var validate:Object = {
		name: [{validator: FormatValidator, format:/\A[a-zA-Z]+\z/}]
	};
}

4.4. PresenceValidator

The presence validator ensures that a property is populated, that a string is not empty or only contains whitespace, and that a number is not NaN. If the property being validated contains an isEmpty property or method, that result will be used for evaluation.

The default message for the presence validator is "can't be empty".

Example:

public dynamic class Person extends Entity
{
	public static var validate:Object = {
		name: [{validator: PresenceValidator}]
	};
}

4.5. (In|Ex)clusionValidator

The inclusion and exclusion validators test if a property either belongs or doesn't belong to a set of values. This set is usually defined as an array, but can be any enumerable object, including an Object, or Dictionary. Note: this set is iterated using a for each..in loop.

Available options:

  • within: Array | Object. Any enumerable object.

The default message for the inclusion validator is "is not included in the list". The default message for the exclusion validator is "is reserved". You can change this message by passing in the message option with a custom message.