Instructor: Next up, let's talk about custom validators.
So sometimes the built-in validators are simply not enough.
And in that case,
we can also build our own custom validators.
And a validator is actually really just a simple function
which should return either true or false.
And if it returns false, then it means there is an error.
And on the other hand when we return true,
then the validation is correct
and the input can be accepted.
Okay, so let's now build a simple custom validator here.
And what I want to validate is if the price discount
is actually lower than the price itself.
That's something that we cannot do
using the built-in validators
and so we're simply gonna build our own.
We need to now specify here an object
for the SchemaType options.
Alright.
So the type is number,
and then to specify our validator
we use the validate property.
Validate, and then as I said,
a simple callback function.
And again, not an arrow function,
but a real function,
because in this function
we're gonna have access to the this variable,
which will point to the current document.
Now if you didn't need the this variable,
then you could of course just use an arrow function.
We have a callback function,
and that callback function actually has access
to the value that was inputted.
So in this case, the price discount that the user specified.
So that's what I call the value, val for short.
Remember that we need to return either
true or false from this validator.
When do we want to return false,
and when do we want to return true?
Well, we want an error when the price discount
is greater or equal than the price.
And so basically what we want to return here
is the test of testing
if the value is less than this.price.
All right, so let's say that the price discount
is 100 and that the real price is 200.
100 is less than 200, true and so we have no error.
And that makes sense because that's exactly what we want.
The price discount should always be lower.
On the other hand, if the discount is 250,
then this turns out to be false.
And then false, remember, will trigger a validation error.
Let's now test it out actually.
Price
(keyboard clacking)
and price discount.
And let's use the values that we used before
and I also need to change the name here.
Okay, so right now our discount is greater than the price
and so we should get our error.
Okay and indeed, we have a validation error.
So failed for path price discount.
Now, we do not have any custom message here
and so let's quickly fix that.
All right and the way we do that is in a very similar way
as we did with the enum.
So we need to actually specify another object
and then set the message property.
Validate
should be an object
and then we have our message in there
and this function here will live
in a property called validator.
Okay and our message here will be
(keyboard clacking)
discount price
should be
below the regular price.
Here we need a comma and so now we're good.
And actually, one very nice trick is that this message here
also has access to the value.
And this works in kind of a weird way
and this really is internal to Mongoose,
so this has nothing to do with JavaScript
so I can simply use the curly braces here and then value.
So this piece here will get access
to the value that was inputted,
so it has the exact same value as this val variable.
So let's test that again
and now indeed we get our message
and even access to the 250 price that we specified here.
Now let's change it to 100 and so now it should work
and yeah, it does.
So, great.
Now there is one very important caveat
that we need to notice here
and that is that inside a validator function,
that this key word is only gonna point
to the current document
when we are creating a new document.
So this function here is not going to work on update.
And so that's very important to note.
You see, that in Mongoose, there are a couple of caveats
that you really need to be aware of
when working with it.
And I learned all of these by experience
and so that's why now I'm able to tell them to you.
So I run into an error once with this one
and so from that time on,
I know that I can only use this kind of validator
with a this keyword in there
when I'm actually creating new documents.
So let me write that down here for you.
(keyboard clacking)
All right, so I hope that you're kind of taking note
of all of these very important small pieces of information
that are very important.
The same thing down here.
Remember that where I told you that
this DOCUMENT MIDDLEWARE only really runs for save
and create but not for update.
And that's one of these other things
that are really important to never forget.
Now in this specific case here,
there are actually ways around fixing this
but they're very complicated and not really worth pursuing.
And we could of course also write validator functions
that do not rely on a this variable.
So in this case, we only need it because we are comparing
one value with the value of another field.
This is a custom validator that we can use in Mongoose
and that we did actually write ourself.
But also, there are a couple of libraries on npm
for data validation that we can simply plug in here
as custom validators that we do not have to write ourselves.
And the most popular library is called validator
and so let's actually take a look at that one.
Validator and then I'm searching for GitHub
because usually all of these libraries are always on GitHub.
And the documentation is also gonna be there
and so here you see
that validator
is a library of string validators and sanitizers.
You also see that it's quite popular with 13,00 stars
and so
that's very good.
We also see this library validates
and sanitize only strings.
Here is then all of the stuff how we install it
and how we use it but that's kind of simple.
We already know that.
But what I want to show you is the list
of all the available validators.
For example, we have isAlpha,
which is gonna check if the string contains only letters.
We have Alphanumeric so only letters and numbers
and we really have a lot of stuff here.
So check if a string is boolian,
or check if the string is a credit card,
so valid credit card number.
Or if it's a currency
or you see really all kinds of different tests.
For example an ISBN, so for checking book numbers.
To test if it's an integer or if the string is lowercase.
And so you see, whenever you need some data validation
you can grab one of these libraries
and simply plug them into your Mongoose validators.
Now many of the things that are here
are actually already built into Mongoose
and so we don't need all of them, okay,
but there is one very specific,
which I want to use, which is isAlpha.
So I want to check if the tour name only contains letters.
And so for that I can use this function
from the validator library.
Let's go back
and start by installing
npm
i
(keyboard clacking)
validator.
That was successful.
Then I need to import it here
and so now we're good to go to actually use it here.
I'm gonna use it here
and again, I use the validate property
and now all I need to do
is to really plug in the function here.
And in validator, it works like this,
where validator is an object
and on there we have then all these methods.
Validator
is
Alpha,
so that's the one that we just choose
from the documentation.
And that's actually it.
So we don't call it here.
We basically just specify
that this is a function that should be used.
Just like our own one, like our own validator,
we didn't call it.
We simply put this callback function here
that it's gonna be called
as soon as the data should be validated.
And so here, it's the same.
Now, if we wanna specify an error message,
it works just like up here.
We can specify an array and then the error message
after the callback function.
And we could have done it down here.
So here we did it differently.
Here we then created this new object
with validator in there and the message,
but we could've done it with an array as well,
but that would've looked weird.
But up here, since the function is so small,
so this is so small, we can simply put it here
and then as a second argument in the array
add the error message.
Tour name must only contain
(keyboard clacking) characters.
Great, check that out.
Back in Postman here, let's get rid of our price discount.
And let's add some number here.
And so that should then fail the test
and indeed, the name must only contain characters.
Let's get rid of that.
We can also not use this name.
We already used it before,
so that can be write out too here with characters
and we still get this error here.
Well, that's probably because of the spaces.
So let's just get rid of the spaces,
which of course is not gonna be real useful
and indeed, now it works.
So the problem was the spaces,
but obviously we want to keep the spaces here.
In fact, this validation error is not really useful
and so I will get rid of it.
Consider that this here was only to demonstrate
that we can use an external library like this
to perform validation.
And actually, we will still use this library a bit later
when we check if the user email is actually valid.
So that's another nice function
that is included in this library.
So again, this is how it works.
Not really useful in this case,
so if we really wanted to test
if the string only contains letters and spaces
it would probably be simpler
to simply use a regular expression
to test for that kind of pattern.
But I'm not gonna do that here
because this lecture was more about
these custom validators.
Anyway, with this lecture, we are now ready
with the introduction to Mongoose.
Now as you can imagine, there is of course
still a lot to learn about Mongoose
and in fact, we have a advanced Mongoose section
a bit later in the course
and of course also in the other sections,
you will keep learning more and more
about how to use Mongoose
in a real professional way.
You have already learned so much up until this point,
so huge congratulations for making it this far
and it's great to see that you're still with me here.
So great job and I hope to see you soon.