Streamline validations
- Lingua principale
- JavaScript
- Stelle
- 2k
- Fork
- 238
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Descrizione
### Rationale
The first thing I noticed when reading the documentation (I'm actually evaluating this project as a suitable ORM for our own project) was the hard-coded base validators and it's lack of flexibility. Reading the issues, I see many tickets on the subject.
Having a non-negligible Zend Framework background, the way validators are handled has inspired many other projects, as it allows effortless flexibility and extensibility. An other such project is [Backbone.Validation](https://github.com/thedersen/backbone.validation).
### Suggestion
So, instead of
```
// Setup validations
User.validatesPresenceOf('name', 'email')
User.validatesLengthOf('password', {min: 5, message: {min: 'Password is too short'}});
User.validatesInclusionOf('gender', {in: ['male', 'female']});
User.validatesExclusionOf('domain', {in: ['www', 'billing', 'admin']});
User.validatesNumericalityOf('age', {int: true});
User.validatesUniquenessOf('email', {message: 'email is not unique'});
```
I would have something like
```
User.validation({
name: {
required: true // true or string, ex: "Name is not specified!"
},
email: {
required: "Email is not specified!" // or true
, unique: "Email is not unique!"
},
password: {
minLength: { min: 5, message: "Password must contain between 5 and 16 caracters" }
, maxLength: { max: 16, message: "Password must contain between 5 and 16 caracters" }
},
gender: {
in: { values: ["male", "femaile"], ignoreCase: true /*, message: .... */ }
},
domaine: {
notIn: ['www', 'billing', 'admin']
},
age: {
integer: true
, min: { value: 18, message: "You must be of legal age!" }
}
});
```
Then, adding new validators could be done like
```
var Schema = require('jugglingdb').Schema;
// signature : add(name, callback, async)
// - name String the validator's name
// - callback Function the validation function :
// - model Object the model instance
// - fieldName String the model field to validate
// - options Object the options configuration
// - callback Function the async callback (optional)
// returns true for success
// returns false or a string (error message) on failure
// - async Boolean if the validation function is async or not (optional) (default false)
Schema.Validation.add("foo", function (model, fieldName, options) {
/* ... */
return true;
});
// async validation must pass a fourth parameter 'cb'
Schema.Validation.add("bar", function (model, fieldName, options, cb) {
setTimeout(function() {
cb(true);
}, 1000);
}, true);
// to use generators, simply provide the async flag and omit the fourth parameter 'cb'
Schema.Validation.add("buz", function * (model, fieldName, options) {
var asyncResult = yield someAsyncCall(model[fieldName], options);
/* ... */
return true;
}, true);
// using each custom validators (the third parameter 'options' will be "true")
User.validation({
name: {
foo: true,
bar: true,
buz: true
}
};
```
### Internationalisation
All error messages should support a `sprintf`-like syntax. With Node, this is supported via the [`util.format`](http://nodejs.org/docs/latest/api/util.html#util_util_format_format) function. The default fallback message on failed validation (if the validation function returns `false`) could be `"'%s' validation failed!"`, which will be formatted with the validated `fieldName`.
To enable translation of these messages, simply provide a function to
```
Schema.Validation.translator(function(message) {
return message; // translated
});
```
Obviously, since all (failed) validation messages are formatted inside the validator functions, before being returned, the translations should also be performed before formatting the message. Therefore, and since we already have a reference to `Schema.Validation`, I would propose
```
var format = require('util').format;
Schema.Validation.add("foo", function (model, fieldName, options) {
return format(Schema.Validation.translate("Foo failed for '%s'!"), fieldName);
});
```
### Integration and Backward compatibility
To support existing projects, all current implementations could remain unchanged and simply proxying to the new validation system, to be deprecated at the next minor release (version 0.3). Thus, the built-in current validators could still be shipped with the ORM, along with new ones provided by the community.
#### `validatesPresenceOf` becomes `required`
##### Options
```
{
message: (defaults to "Field %s is required.")
}
```
The model field must be specified, with any given value.
#### `validatesLengthOf` becomes `minLength` and `maxLength`
##### Options
```
{
min: (defaults to 3)
, max: (defaults to 255)
, message: (defaults to "Field '%s' must contain more|less than %d character(s)")
}
```
For strings, check it's `length` property. Ignored for any other type.
#### `validatesInclusionOf` becomes `in`
##### Options
```
{
values:
, strictCompare: (defaults true)
, ignoreCase: (defaults false)
, message: (defaults to "Invalid field value '%s'")
}
```
The `values` array items' type should be compatible with the model's field type.
#### `validatesExclusionOf` becomes `notIn`
##### Options
```
{
values:
, strictCompare:
, ignoreCase: (defaults false)
, message: (defaults to "Invalid field value '%s'")
}
```
The `values` array items' type should be compatible with the model's field type.
#### `validatesNumericalityOf` becomes `number`, `integer`, `decimal`, or `finite`
##### Options
```
{
message: (defaults to "Invalid numeric value '%s'")
}
```
For `number`, the value must be _any_ numeric value.
For `integer`, the value must be an integer value.
For `decimal`, the value must _not_ be an integer value.
For `finite`, the value must be _finite_.
#### `validatesUniquenessOf` becomes `unique`
##### Options
```
{
message: (defaults to "%s must be unique.")
}
```
This validator checks in all the set for another model with the same field value. This validator is asynchronous.
### Other proposed validations
From the [sails.js](http://sailsjs.org/#!documentation/models) framework.
- empty
- notEmpty
- undefined
- string
- alpha
- alphanumeric
- email
- url
- urlish
- ip
- ipv4
- ipv6
- creditcard
- uuid
- uuidv3
- uuidv4
- falsey
- truthy
- null
- notNull
- boolean
- array
- date
- hexadecimal
- hexColor
- lowercase
- uppercase
- after
- before
- is
- regex
- not
- notRegex
- equals
- contains
- notContains
- len
- max
- min
Guida per i contributori
Nessuna guida per i contributori indicizzata per questo repository
Direzione di ricerca
L'issue propone una revisione importante del sistema di validazione in jugglingdb. Inizia esaminando i metodi di validazione esistenti nella codebase, probabilmente in file come lib/validations.js o simili. Comprendi come sono implementati i validatori attuali come validatesPresenceOf. L'obiettivo è progettare una nuova API di validazione che supporti un formato dichiarativo, validatori personalizzati e l'internazionalizzazione. Ciò richiede una profonda familiarità con l'architettura dell'ORM e probabilmente comporta modifiche in più file.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- javascript, nodejs
- Ambito
- api, backend, databases
- Tipo di issue
- Funzionalità
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Stato di attività
- Ferma
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 25/100