Validations

Validations are handled by Anchor which is based off of Node Validate and supports most of the properties in node-validate.

Validations are defined directly in your Collection attributes. In addition you may set the attribute type to any supported Anchor type and the ORM will build a validation and set the schema type as
a string for that attribute.

Validation rules may be defined as simple values or functions (both sync and async) that return the value to test against.

Available validations are:

attributes: {
example: {
empty: true,
required: true,
notEmpty: true,
undefined: true,
string:
alpha: true,
numeric: true,
alphanumeric: true,
email: true,
url: true,
urlish: true,
ip: true,
ipv4: true,
ipv6: true,
creditcard: true,
uuid: true,
uuidv3: true,
uuidv4: true,
int: true,
integer: true,
number: true,
finite: true,
decimal: true,
float: true,
falsey: true,
truthy: true,
null: true,
notNull: true,
boolean: true,
array: true,
date: true,
hexadecimal: true,
hexColor: true,
lowercase: true,
uppercase: true,
after: '12/12/2001',
before: '12/12/2001',
is: /ab+c/,
regex: /ab+c/,
not: /ab+c/,
notRegex: /ab+c/,
equals: 45,
contains: 'foobar',
notContains: 'foobar',
len: 35,
in: ['foo', 'bar'],
notIn: ['foo', 'bar'],
max: 24,
min: 4,
minLength: 4,
maxLength: 24
}
}

Validations can also be defined as functions, either sync or async.

attributes: {
website: {
type: 'string',
contains(cb) {
setTimeout(() => { cb('http://') }, 1)
}
}
}

Validations can also be used against other attributes using the this context.

attributes: {
startDate: {
type: 'date',
before() {
return this.endDate
}
},

endDate: {
type: 'date',
after() {
return this.startDate
}
}
}

Validation rules

Name of validator What does it check? Notes on usage
after check if string date in this record is after the specified Date must be valid javascript Date
alpha check if string in this record contains only letters (a-zA-Z)
alphadashed does this string contain only numbers and/or dashes?
alphanumeric check if string in this record contains only letters and numbers.
alphanumericdashed does this string contain only numbers and/or letters and/or dashes?
array is this a valid javascript array object? strings formatted as arrays won’t pass
before check if string in this record is a date that’s before the specified date
binary is this binary data? If it’s a string, it will always pass
boolean is this a valid javascript boolean ? strings will fail
contains check if string in this record contains the seed
creditcard check if string in this record is a credit card
date check if string in this record is a date takes both strings and javascript
datetime check if string in this record looks like a javascript datetime
decimal contains a decimal or is less than 1?
email check if string in this record looks like an email address
empty Arrays, strings, or arguments objects with a length of 0 and objects with no own enumerable properties are considered “empty” lo-dash _.isEmpty()
equals check if string in this record is equal to the specified value === ! They must match in both value and type
falsey Would a Javascript engine register a value of false on this?
finite Checks if given value is, or can be coerced to, a finite number This is not the same as native isFinite which will return true for booleans and empty strings
float check if string in this record is of the number type float
hexadecimal check if string in this record is a hexadecimal number
hexColor check if string in this record is a hexadecimal color
in check if string in this record is in the specified array of allowed string values
int check if string in this record is an integer
integer same as above Im not sure why there are two of these.
ip check if string in this record is a valid IP (v4 or v6)
ipv4 check if string in this record is a valid IP v4
ipv6 check if string in this record is aa valid IP v6
is something to do with REGEX
json does a try&catch to check for valid JSON.
len is integer > param1 && < param2 Where are params defined?
lowercase is this string in all lowercase?
max
maxLength is integer > 0 && < param2
min
minLength
not Something about regexes
notContains
notEmpty WTF
notIn does the value of this model attribute exist inside of the defined validator value (of the same type) Takes strings and arrays
notNull does this not have a value of null ?
notRegex
null check if string in this record is null
number is this a number? NaN is considered a number
numeric checks if string in this record contains only numbers
object checks if this attribute is the language type of Object Passes for arrays, functions, objects, regexes, new Number(0), and new String(‘’) !
regex
required Must this model attribute contain valid data before a new record can be created?
string is this a string ?
text okay, well is this a string ?
truthy Would a Javascript engine register a value of false on this?
undefined Would a javascript engine register this thing as have the value ‘undefined’ ?
uppercase checks if string in this record is uppercase
url checks if string in this record is a URL
urlish Does the string in this record contain something that looks like a route, ending with a file extension? /^\s([^\/]+.)+.+\s*$/g
uuid checks if string in this record is a UUID (v3, v4, or v5)
uuidv3 checks if string in this record is a UUID (v3)
uuidv4 checks if string in this record is a UUID (v4)

Custom Validations

You can define your own types and their validation with the types object. It’s possible to access and compare values to other attributes. This allows you to move validation business logic into your models and out of your action logic.

exports.default = {
types: {
point(latlng) {
return latlng.x && latlng.y
},

password(password) {
return password === this.passwordConfirmation
}
},

attributes: {
firstName: {
type: 'string',
required: true,
minLength: 5,
maxLength: 15
},

location: {
type: 'json',
point: true
},

password: {
type: 'string',
password: true
},

passwordConfirmation: {
type: 'string'
}
}
}

Lifecycle Callbacks

Lifecycle callbacks are functions you can define to run at certain times in a query. They are hooks that you can tap into in order to change data. An example use case would be automatically encrypting a password before creating or automatically generating a slugified url attribute.

Callbacks on create

Example

If you want to encrypt a password before saving in the database you can use the beforeCreate lifecycle callback.

exports.default = api => {
const UserModel = {

attributes: {

username: {
type: 'string',
required: true
},

password: {
type: 'string',
minLength: 6,
required: true,
columnName: 'encrypted_password'
}

},

// Lifecycle Callbacks
beforeCreate(values, next) {
api.hash.hash(values.password).then(hash => {
values.password = hash
next()
})
}
}

return UserModel
}

Callbacks on update

Example

You’re the NSA and you need to update the record of a person who is a suspect! First though, you need to make sure that the record concerns a person of interest. You might want to use the beforeValidation lifecycle callback to see if the record’s citizen_id exists in your Probable_suspects model.

{
attributes: {
citizen_name: 'string',
phone_records: 'array',
text_messages: 'array',
friends_and_family: 'array',
geo_location: 'json',
loveint_rating: 'integer',
citizen_id: 'integer'
},

beforeValidate(citizen_record, next) {
ProbableSuspectsModel.findOne(citizen_record.citizen_id)
.then(suspect => {
if (!suspect) { throw new Error('This citizen is not a suspect') }
next()
})
.catch(error => { next(err) })
}
}

Note that in the example above, the ProbableSuspectsModel would have had got from the api.models.get method.

Callbacks on destroy

Example

You want to update a cache to remove a record after it has been destroyed. To do this you can use the afterDestroy lifecycle callback.

{
attributes: {
name: 'string'
},

afterDestroy (deletedRecord, next) {
api.cache.destroy(`person_${deletedRecord.id}`, (error, destroyed) => {
next()
})
}
}