In this video you're going to learn how to set up a TTP end points for updating resources.
Together we'll focus on updating a user and in the next video it will be your challenge to update a
task so down below at the end of our three user related end points.
We're gonna go ahead and add a fourth right here.
This will be using app dot patch the patch each TTP method which is designed for updating an existing
resource.
So right here we'll set up the path for this particular endpoint.
That's gonna be the same as what we have above.
So here we are trying to get an individual user by its I.D..
Down below we are trying to update an individual user by its I.D..
So that would be forward slash users forward slash colon I.D. then we'll set up our async function.
So right here a sync will set up the two arguments request and response then we'll go ahead and finish
off the syntax for the Arrow function.
Now the first thing we're gonna do inside of here is set up that try catch block and we're going to
attempt to update the user with the provided I.D..
Let's go ahead and set the try catch block up.
So we tried to do something update a user by its I.D. And if that doesn't go well we will get the error
in the catch block down below.
Now for the catch block what we're gonna do is hold off for the moment and we'll go ahead and start
with try.
Now the Mongoose method we're gonna use to get this done is available in that query is the list we've
been looking at right here up top on the queries guide.
We have find a bi I.D. and update.
Now we have other update methods as well such as find one and update update and update many though we'll
be sticking with this one though technically you can get the job done with any of those four.
Let's go ahead and get started over in sign of the try.
BLOCK Right here what we're gonna get back from find by I.D. and update is going to be the user.
So const user equals we'll go ahead and use await to await the promise that comes back from user dot
find by I.D. and update.
Perfect.
Now the first argument we'll pass in is the idea of the user we're attempting to update and we already
know where we can access that that is request dot parameter dot I.D..
This is exactly what we did up above for getting the I.D. for the user.
We were trying to read then down below the next argument is the updates we're trying to make now unlike
with the Mongo D.B. native driver there's no need to use anything like these set.
Operator Mongoose handles all of that for us.
Another great reason to actually use the tool.
So right here all we have to do is provide the object with the various fields we want to update.
So if I wanted to update the name I could set a name equal to some new string like Jessica.
Now in this case we don't want to have a static update where we always update the user to the same thing.
What we want to do is take the updates in as the request body.
So much like we did for creating a user.
The data will be passed through via the TTP request.
So right here we are going to access request dot body.
Excellent.
This is exactly what we did up just a little bit in the code when we originally created the user.
Now back down below in the patch route we can go ahead and provide the third argument which is an options
object.
And here we are going to set up a couple of options to get things working the way we want them.
The first option is new and we'll be setting new equal to true.
This is going to return the new user as opposed to the existing one that was found before the update.
So right here we'll have back the latest data the original user with the updates applied.
Next up the second option we're going to set is run validators.
This is going to make sure that we do run validation for the update.
So if I tried to update my name to something non-existent I want to make sure that fails any time we're
allowing the user to write data to the database.
We want to make sure we validate it so that it comes in the format we're expecting.
Now right here there are a couple of different things that could happen.
One the update went well to the update went poorly.
And 3 there was no user to update with that I.D. And we want to make sure that we handle all three.
First up if there was no user with that I.D. There will be no value right here.
So if there is no user what are we going to go ahead and do.
Well we'll be sending back a 4 0 4.
So I'll use return to stop the function execution and I'll use response dot status to set a 4 0 4.
And finally I'll use send to actually send it back.
Now if the code down below right here runs that means everything went well.
I can stick with these two hundred status code which is the default value all I'll do is use response
dot send to send the user data back.
So if someone updates the user we want to send them back the current user data that would be all of
the existing data with their updates applied.
Now the next case is down below in catch.
This is going to run if something goes wrong.
Now this could be one of two things.
It's possible that we have an error like the other ones we've talked about where we want to send back
a five hundred because we weren't able to connect to the database or something along those lines a server
related issue.
It's also possible that it's a validation related issue where someone has tried to update their name
and they've tried to set it equal to an empty string as an example which would not be valid based off
of the model we set up for a user.
For the moment we're not going to worry about handling both cases.
We'll just focus on handling validation.
So that would be response dot status and we'll send back a 400.
This is exactly what we did up above when creating a user went wrong.
Then we'll go ahead and send the error back right here dot send sending back the error object now that
we have this in place we have that route completely set up.
I can save the program and go ahead and test this out from here.
We'll be moving over into postmen to make sure the routes working as expected.
I'm going to go ahead and create a brand new request over here for the task app we'll be setting this
one up with a name like update user once I save it.
The first thing we're gonna do is crack it open and switch up the TTP method.
We are going from get over to patch.
Then we'll provide the U.R.L..
Now we are going to need the I.D. of someone to update.
I can always use read users to get a list of all of my users back and pick one that I'd like to change.
So right here I have a few different ones.
I'll go ahead and grab the I.D. for this first user.
Now I'll go back over to the update user request and complete the you are out.
That's local host colon.
Three thousand forward slash users forward slash some I.D. Now in order to actually set up the updates
we do want to provide the body so we'll go to Body raw and we'll switch from text over to Jason like
we had done for our to create requests right here.
We'll be able to provide the Jason describing what exactly we would like to change and in our case I'm
gonna add a last name onto the name.
So right here I will be updating name.
I'll go ahead and change it from Andrew over to Andrew Meade.
Now if I go ahead and fire this off I would expect a two hundred status code as the response with my
updated user as the response body down below.
That is exactly what I end up getting.
So right here I am indeed able to update the user as expected.
Now if we were to swap out that I.D. with something that did not exist I would get the 4 0 4 and if
we were to go back to the I.D. that was valid but try to update in an invalid way I would expect to
see that four hundred.
So right here I have the valid I.D. once again and I'll try to set the name equal to nothing an empty
string.
When I do that down below I get a four hundred bad request with my validation error showing up.
So here we can see that we are indeed able to update the user as expected.
Now if we tried to update a property that the user didn't have it would be completely ignored.
So right here the only thing I'm gonna try to update is height now height is not something we track
for users though I'll try to set it equal to 72.
That would be my height in inches if I go ahead and send this off down below.
We're gonna see our user object but we're not going to see a height property so any of those properties
that don't exist on the user will be completely ignored.
Now you'll notice we're getting a two hundred.
That's because once again mongoose is ignoring them.
If you wanted to set up an error response you would have to add some custom code to get that done and
I'll show you how to do that right now.
So let's say we want to send back a 400 when you tried to update a property that's not something you
can actually change.
This would be something like underscore I.D. which you can't update or something like height which doesn't
exist in the first place to get this done.
The first thing we want to do is figure out what someone should be allowed to update.
And we're going to store this in and allowed updates array right here we can list out the individual
properties we would like someone to be able to change.
This is going to be an array of strings so I'll allow the updating of name email password.
And finally H.
Everything else will be considered invalid.
Next up we have to figure out what they're trying to update with this operation.
Now we know that request not Bonnie is an object with all of those updates.
But what I want back is an array of strings similar to what I have here.
And I'd like to store on a another variable which I'll call updates.
Now to get this done to convert our object into an array of its properties we'll be using object dot
Keats right here we pass in the object we're trying to work with.
So it's going to take this object in and keys will return an array of strings where each is a property
on that object.
Now if I was to use this example data I would have an array with a single item inside the string height
as that's the only property we're trying to update.
Now the next thing we want to determine is if every single update can be found in allowed updates.
If almost all of them are.
That's not enough.
Every single one needs to exist inside of here.
If we're trying to update something that doesn't exist we'll consider the whole operation a failure.
Now to track this we can use a boolean is valid operation or something similarly named and what we're
going to do is use an Array method.
You might not have used before.
This is every now we're gonna use it on updates so it will be updates dot every which we'll call as
a function.
Now every like most of our array methods it takes a callback function as its one and only argument and
this callback function gets called for every item in the array.
So for every attempted update we get access to the individual item right here.
So if I'm trying to update five properties this function would get called five times with those five
different property names.
Now it's up to us to return true if the update is allowed and false otherwise.
So every is going to run your function for every item in the array.
If you always get true as the return value every will return true.
If you don't always get true back every will return false.
So if I have 10 truths then every will return true if I have nine truths and a single false every will
return false.
Now this is exactly what we want we're going to return and we're going to see if the update is included
in allowed updates so allowed updates dot includes which returns a boolean true if it's included and
false otherwise and we'll just check if that individual update is found right here we have exactly what
we would need.
Now we can use the arrow function shorthand.
So here we are just returning the following.
I can take that I can remove the curly braces and I can paste it right here making sure to have the
closing parentheses which matches up with the opening one for the every call.
Now all we have to do is see what is valid.
Operation exists.
Excuse me.
What equals two.
So right here if we want to check if it's false.
So if it is not a valid operation we're gonna go ahead and stop things by using return.
I'll use response dot status to send back a four hundred and then I can use send to send back an object
and we will set up an error property right here.
I could provide an error like the following invalid updates.
Excellent.
Next up what is the actual condition.
Well I want to run this code if is valid.
Operation is false so is valid operation.
Now this is only going to run if it's true in order to reverse that.
We use the logical not operator to flip the boolean from either true to false or false to true.
So right here we have the exact same update logic but with a little additional error handling making
sure that the user is using the operation correctly.
As mentioned it's not going to impact the functionality you already weren't able to update properties
that didn't exist.
The goal here though is to provide the user with as much information as possible as to why things aren't
going as expected.
If I tried to update the height to 72 and I got a success status code but I didn't see it down below
I could be a little confused.
But now if I go ahead and fire off the same operation I get a four hundred with invalid updates showing
up which is fantastic.
Now once again let's go ahead and try to update something valid and make sure that still works.
Right here I'll try to change the name one more time and I'll go ahead and change it to jets.
If I fire that off I do get a two hundred and I can see that property updated down below.
So there we go.
That's how we'll be setting up HDTV routes for up dating a given resource.
Now some of our end points are going to have logic that's a little more complex than others and that's
OK because some are indeed simpler than others.
In general the routes for updating resources are the most complex.
So here we can see we do have more code in a single express route handler than we've had before.
Now that we've done this once together with users in the next video it's going to be your challenge
to do something similar for tasks.
I'm excited to get to that.
So let's go ahead and jump right in.