Skip to content
This repository has been archived by the owner on Dec 12, 2021. It is now read-only.

Validators should have the option to skip all other validators on failure. #101

Closed
jpbufe3 opened this issue Mar 16, 2016 · 5 comments
Closed

Comments

@jpbufe3
Copy link

jpbufe3 commented Mar 16, 2016

Certain validators, such as length, rely on an object being of a certain type or having a certain value. An easy way to ensure this is by having a type validator come first (as in #80). However, even when doing so, the length validator will still be called on an empty object after the type validator fails and creates a console log that the length attribute is non numeric.

Example:

validate.validators.type = ...; // See #80
var constraints = {
    id : {
        type : 'string',
        length : { maximum : 32 }
    }
};
validate({ id : true }, constraints);

This will log ERROR: '[validate.js] Attribute id has a non numeric value for length' to the console in addition to returning an error for being the wrong type and an error for being the incorrect length. The preferred behavior would be to ONLY receive the error for being the wrong type.

Ideally, each validator could have an optional attribute called exit that defaults to false, but when set to true, will skip all future validators when it errors.

Example:

var constraints = {
    id : {
        type : {
            value : 'string',
            exit : true
        },
        length : { maximum : 32 }
    }
};

Maybe this should go in a separate issue - but it seems like https://github.com/ansman/validate.js/blob/master/validate.js#L781 could be removed and replaced with a different error message. Length currently has the wrongLength, tooShort and tooLong messages. Another one, nonNumericLength, could be added to account for this scenario.

@ansman
Copy link
Owner

ansman commented Mar 21, 2016

Since validators are not ordered this isn't really possible.
You can however use the detailed format to inspect the results and remove all but one you want yourself.

@jpbufe3
Copy link
Author

jpbufe3 commented Mar 21, 2016

@ansman: is there a reason the validators aren't ordered?

Thoughts on adding the additional error condition to the length validator and removing the log line?

@ansman
Copy link
Owner

ansman commented Apr 10, 2016

They are not ordered because they are keys in an object which are not ordered.

@tilleps
Copy link

tilleps commented May 17, 2016

I created a wrapper for the validate.async method that accepts an array of constraints. The idea is to set different groups of validators and break/skip the next set of constraints should they fail.

Example Usage

var data = {
  email: "example@github.com"
};

var constraints = [
  {
    email: {
      presence: true
    }
  },
  {
    email: {
      checkDatabaseValidator: true
    }
  }
];

validate.isValid(data, constraints, function (values) {
  // do things with validated data
}, function (errors) {
  // invalid
});

// or promise support

validate.isValid(data, constraints)
.then(function (values) {
  // do things with validated data
}, function (errors) {
  // invalid
});

In the above example, if data's email was blank, the validation chain would break and would not attempt to run the checkDatabaseValidator

Wrapper

validate.isValid = function (data, constraints, successCallback, failCallback) {
  return new Promise(function (resolve, reject) {
    constraints = Array.isArray(constraints) ? constraints : [constraints];

    var combinedValues = {};


    var iterate = function (constraints) {

      var constraint = constraints.shift();    

      if (!constraint) {
        resolve(combinedValues);

        //  Support for callbacks
        if (successCallback) {
          successCallback(combinedValues);
        }

        return;
      }


      this.validate.async(data, constraint)
        .then(        
          //  Success, validate next group/set
          function (values) {

            //  Merge values to return
            for (var key in values) {
              combinedValues[key] = values[key];
            }

            iterate(constraints);      
          },

          //  Fail, stop further validation
          function (errors) {
            reject(errors);

            //  Support for callbacks
            if (failCallback) {
              failCallback(errors);
            }            
          }
        );

    }.bind(this);


    iterate(constraints); 
  }.bind(this));

};

@ansman
Copy link
Owner

ansman commented May 20, 2016

Interesting idea, feel free to open a pull request

@ansman ansman closed this as completed Nov 12, 2017
# for free to subscribe to this conversation on GitHub. Already have an account? #.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants