Open vict-shevchenko opened 7 years ago
Hi, I have forked a repo and started some debugging in order to fix this. But came to pretty strange results.
The problem is in support of Arrays in rules. Consider a situations
var values = { emails: ['test@test.io'] };
var rules = { emails: ['email'] };
var v1 = new Validator(values, rules);
v.passes() // true.
But this true
is incorrect true, because validation happened on not on string 'test@test.io'
rather on Array ['test@test.io']
. And RegExp /email regExp/.test(['test@test.io'])
returns true. So inputValue
that was aimed to be validates was incorrect.
That cause situations
var values = { emails: ['test@test.io', 'whatever'] };
var rules = { emails: ['email', 'required'] };
var v1 = new Validator(values, rules);
v.passes() // false.
And this is incorrect now.
Despite things are ok if we use flat rules object, like:
var rules = {emails[0]: 'email', emails[1]: 'required' }
What I have found for now, is that if we have in rules
user:{name: 'required'}
-> user.name: required
)
_flattenObject
function is responsible for that. And I suppose all nested data structures should be flattened.
This may be a massive influence on a lib, taking to account that now it relays on wrong behavior.
Let me know if I am on a right direction. I may have not got the reason why Arrays are not flattened.
Thanks @skaterdav85 , @mikeerickson , @LKay
Do you know how Laravel handles an array of emails? If they don't, maybe you can just create a custom rule.
So, I did some more investigation on that topic, and it happens that currently there is a similar limitation. Both libraries support "alternative initialization using an array instead pipe" and this makes rules having nested Arrays impossible to use.
var values = { email: 'test@test.io' };
var rules = { email: ['required', 'email'] }; // email in value is not an Array
So in this scenario we dont have one to one match between rules and values data format. Like I expected to have. So any array in
rulesobject is counted ad rules list, not as
values` structure mirroring.
To conclude, if we need to validate only first item of array, we need to write flat rule name.
var values = { emails: ['test@test.io'] };
var rules = { 'emails[0]': 'required|email' }; // or {'email[0]': ['required', 'email']}
This item really confused me for some time. Don`t you mind if I add this to README in PR?
Sorry to dredge up a very old issue, but I somewhat recently needed the same thing that is asked for in this ticket. I ended up running my own slightly modified copy of _flattenObject
against my ruleset before it is passed into the validator so that the plugin itself didn't need to do any parsing, and it correctly flattens out the nested array object and correctly attaches the nested rules to each key within the sub-object.
(my codebase is written in typescript, so ignore the castings against the variables and it functions as javascript)
function FlattenObject(obj: Record<string, any>): Record<string, any> {
const flattened: Record<string, any> = {};
function recurse(current: Record<string, any>, property?: any) {
if (!property && Object.getOwnPropertyNames(current).length === 0) {
return;
}
if (Object(current) !== current || Array.isArray(current)) {
if (Array.isArray(current) && current[0] instanceof Object && property) { // <-- Additional check when we know it may be an array to see if the first item is an object, and assume that it is reading nested rules if so
flattened[property] = ['array'];
recurse(current[0], `${property}.*`); // <-- recurse down into the sub-object to attach the ruleset to each part of the array with the appropriate "key.*.subKey" structure
} else {
flattened[property] = current;
}
} else {
let isEmpty = true;
for (const p in current) {
if (Object.prototype.hasOwnProperty.call(current, p)) {
isEmpty = false;
recurse(current[p], property ? `${property}.${p}` : p);
}
if (isEmpty) {
flattened[property] = {};
}
}
}
}
if (obj) {
recurse(obj);
}
return flattened;
}
This has been working for me for a little bit now, so if it's wanted I can open a PR to adjust the flatten process to take nested array rules into account
Hi, thanks a lot for an awesome library.
I suppose I have found an inconstancy, here what it is:
In my opinion both of them should work. If this is a bug, I can try to make a pull request. Thanks.