Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(validation): add section on global schematype validation, clean up other issues #12466

Merged
merged 3 commits into from
Sep 25, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 27 additions & 13 deletions docs/validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,20 @@ Before we get into the specifics of validation syntax, please keep the following
[require:Validation$]
```

- [Built-in Validators](#built-in-validators)
- [Custom Error Messages](#custom-error-messages)
- [The `unique` Option is Not a Validator](#the-unique-option-is-not-a-validator)
- [Custom Validators](#custom-validators)
- [Async Custom Validators](#async-custom-validators)
- [Validation Errors](#validation-errors)
- [Cast Errors](#cast-errors)
- [Global SchemaType Validation](#global-schematype-validation)
- [Required Validators On Nested Objects](#required-validators-on-nested-objects)
- [Update Validators](#update-validators)
- [Update Validators and `this`](#update-validators-and-this)
- [Update Validators Only Run On Updated Paths](#update-validators-only-run-on-updated-paths)
- [Update Validators Only Run For Some Operations](#update-validators-only-run-for-some-operations)

### Built-in Validators

Mongoose has several built-in validators.
Expand Down Expand Up @@ -107,6 +121,15 @@ fails. That means your custom validators may assume `v` is `null`,
[require:Cast Errors]
```

### Global SchemaType Validation

In addition to defining custom validators on individual schema paths, you can also configure a custom validator to run on every instance of a given `SchemaType`.
For example, the following code demonstrates how to make empty string `''` an invalid value for _all_ string paths.

```javascript
[require:Global SchemaType Validation]
```

### Required Validators On Nested Objects

Defining validators on nested objects in mongoose is tricky, because
Expand Down Expand Up @@ -148,15 +171,6 @@ not defined.
[require:Update Validators and `this`]
```

### The `context` option

The `context` option lets you set the value of `this` in update validators
to the underlying query.

```javascript
[require:The `context` option]
```

### Update Validators Only Run On Updated Paths

The other key difference is that update validators only run on the paths
Expand All @@ -178,10 +192,10 @@ following update operators:

- `$set`
- `$unset`
- `$push` (>= 4.8.0)
- `$addToSet` (>= 4.8.0)
- `$pull` (>= 4.12.0)
- `$pullAll` (>= 4.12.0)
- `$push`
- `$addToSet`
- `$pull`
- `$pullAll`

For instance, the below update will succeed, regardless of the value of
`number`, because update validators ignore `$inc`.
Expand Down
63 changes: 27 additions & 36 deletions test/docs/validation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,33 @@ describe('validation docs', function() {
// acquit:ignore:end
});

it('Global SchemaType Validation rray', async function() {
vkarpov15 marked this conversation as resolved.
Show resolved Hide resolved
// Add a custom validator to all strings
mongoose.Schema.Types.String.set('validate', v => v == null || v > 0);

const userSchema = new Schema({
name: String,
email: String
});
// acquit:ignore:start
db.deleteModel(/User/);
// acquit:ignore:end
const User = db.model('User', userSchema);

const user = new User({ name: '', email: '' });

const err = await user.validate().then(() => null, err => err);
err.errors['name']; // ValidatorError
err.errors['email']; // ValidatorError
// acquit:ignore:start
assert.ok(err);
assert.equal(err.errors['name'].name, 'ValidatorError');
assert.equal(err.errors['email'].name, 'ValidatorError');

delete mongoose.Schema.Types.String.defaultOptions;
// acquit:ignore:end
});

/**
* Defining validators on nested objects in mongoose is tricky, because
* nested objects are not fully fledged paths.
Expand Down Expand Up @@ -503,42 +530,6 @@ describe('validation docs', function() {
assert.ok(error);
});

/**
* The `context` option lets you set the value of `this` in update validators
* to the underlying query.
*/

it('The `context` option', async function() {
// acquit:ignore:start
const toySchema = new Schema({
color: String,
name: String
});
// acquit:ignore:end
toySchema.path('color').validate(function(value) {
// When running update validators, `this` refers to the query object.
if (this.getUpdate().$set.name.toLowerCase().indexOf('red') !== -1) {
return value === 'red';
}
return true;
});

const Toy = db.model('Figure', toySchema);

const update = { color: 'blue', name: 'Red Power Ranger' };
// Note the context option
const opts = { runValidators: true, context: 'query' };

let error;
try {
await Toy.updateOne({}, update, opts);
} catch (err) {
error = err;
}

assert.ok(error.errors['color']);
});

/**
* The other key difference is that update validators only run on the paths
* specified in the update. For instance, in the below example, because
Expand Down