Jonas: Let's continue creating some factory functions,
this time for updating and for creating some resources.
And so, now that we already know how it works,
it's really simple to just continue doing the same
for updating.
So exports.updateOne,
and let's actually go ahead and copy the code again
from the tour controller.
Okay.
And we have a ton of files now open
because we're actually changing all of them
kind of at the same time.
So let's copy this,
and paste it here.
And so, what we're interested in is, again, this part.
Okay.
And now, of course, we need to create that factory function
because we don't want to return this.
Instead, we want to return a function,
which is then, in turn, going to return this.
Right?
So that's very simple.
We use a simple arrow function where we pass in the model
and then implicitly return whatever comes after the arrow.
So, all of this.
All right.
So just like before, let's replace the specific model
with a general one,
and then replace all of this here with document.
Or actually, with doc, as we did it before.
And here it's no document,
and then down here, where we actually send the data,
it would be nice to actually give it the property name
of the data that we're sending.
For example, reviews, and then the document, or tours.
Okay.
But that's a bit too much work to implement it right now.
And so, I'm simply going to leave it like this
where I sent, again, data.
All right.
So went went our data here,
and then the envelope in there is, again,
going to be called data.
All right.
And so, this should work now
because everything else is really just the same.
And so, we can go ahead, get rid of all of this,
and simply say
factory.updateOne,
pass in the Tour model, and call it a day.
All right?
So, really simple.
Next, the same thing for the users.
So again, we have updateUser.
This route is not yet implemented.
And so, let's simply replace all of this here
with our factory function updateOne.
All right.
And so, just like before, this updateUser function
is only for administrators, okay?
And only for updating data that is not the password,
because remember, whenever we use, where is that,
so whenever we use findById and update,
all the safe middleware is not run.
So remember how we talked about that a couple of times.
And so, again, it's really important
that we do not attempt to change passwords here
using this updateUser.
Okay?
Let's actually write that here.
With this.
Great.
And now, finally, also,
let's put it in the review controller.
All right.
So exports.updateReview,
and then our Review.
So that one is very simple.
Let's now go ahead and add these routes to Postman, as well.
So we have Delete Review,
and now let's simply add it here as PATCH.
And the thing we also need to still implement the route
in the review router.
So let's do that as well.
But first, I'm going to save it here in reviews.
So Update Review.
So here, in the review routes,
we should add the patch method,
and then reviewController.updateReview.
All right.
So let's take a look at one of these reviews here,
let's say this one, and update the rating to four.
Okay.
So the body,
set it to four.
And send it now.
Okay, and as we can see, we get our new review back
with the rating updated, just as expected.
And again, we're going to take care of authorization
a bit later in the section.
For now, I just wanted to make this work.
So users, let's now also update users.
Okay?
So GET, and PATCH.
So let's Get All Users here.
Let's say this one.
And let's change the name
to Administrator,
which before was simply admin.
All right?
And so, this one worked as well.
Okay, so again, I'm saving all of this here in my collection
because then, a bit later,
I can actually go ahead and create documentation
from all of this collection data that we have here.
So Update User,
put that one here, and this one here.
Perfect.
So updating users is now working
for all of our three resources using the factory function.
And so, let's go ahead and add the next one,
which is gonna be createOne.
So exports, createOne.
And again, we pass in the model.
And from there, we create a new function.
And that may, once again,
actually copy it from the Tour here.
All right.
And so, what we need here is only this part.
So model, and document.
And down here, we again call it data.
All right.
And so, that's actually it.
That is our factory function.
And so, again, let's come here and replace it.
So factory.createOne, Tour.
So you see that our code in the controllers
is now getting really clean, right?
But actually, we're not gonna be able to replace
all of the functions that we have here with factories,
because otherwise, we wouldn't even need
this controller file, right?
We could then simply create these handlers on the fly,
basically, in the router file, right?
And so, we could basically skip this entire step
of the controller file.
But again, we still need it
because we have some other stuff in there.
For example, these methods here
for getting the tour statistics, or this monthly plan,
and yeah.
So it makes sense to actually keep this file, okay?
So next up, for the Users,
we actually do not need the createOne
because, for creating new users,
we already have the signUp function,
and we cannot really replace that with a factory
because it really is different from this generic one.
Okay?
But we can do it in the review controller, okay?
So basically, we want to replace this createReview.
Now you see that also, in this one,
we have some additional step.
So we have this code that is also not
in our generic createOne function.
And so, how can we fix that?
Well, we can actually create a middleware
that is going to run before the createReview, okay?
And so, that actually also makes it a bit more decoupled.
So basically, this code here is then gonna be
in its own function,
and really decoupled from createReview,
because actually, it doesn't have much to do
with creating the review.
It simply sets some data, right?
And so, let's actually call this set tour and user IDs.
So request, ah, the response is missing.
Okay?
And all we're gonna do here
is to basically set these IDs on the body
and then move straight to the next middleware,
where then the review is actually created.
Alright?
So before we forget it,
let's then actually add this middleware.
So in the review routes, it's right here in post.
So reviewController, setTourUserIds.
Okay?
So yet another middleware function in this stack.
Okay.
Anyway, let's then get rid of what we have here
because this is easily replaceable
with our factory function, once more.
So createOne, then the Review, and that's it.
Okay.
And just to test if this still works,
let's simply go ahead and create a new review on Tour.
Okay?
And for that, we need the tour IDs,
so let's also say Get All Tours.
And now we get the user belonging is no longer existing,
so let's simply go ahead and log in again.
So get a new token here.
And so, there we go, as an admin.
So now, Get All Tours, here we go.
Let's just choose one of them.
So let's say, The Forest Hiker.
I think this one already has some reviews, doesn't it?
Oh no, it doesn't.
So this one is a good one to try it out now.
And so, Create New Review on Tour.
Remember, we have to change the ID here.
And now we can post this review
only with the rating and the review.
But I think it's actually not going to work
because we're logged in as an administrator,
and only regular users can post reviews.
Okay?
All right, so let's still do this here.
Mind blowing.
But we're gonna get this error that I was just saying.
So you do not have permission to perform.
And so, we need to log in again,
this time as a different user.
And let's take a look at which one we have, actually.
Ah, okay.
So let's just use test.
Or maybe test was the one with the wrong password.
But let's see.
Ah, yeah.
So let's experiment with testuser.
And this one works.
And so, actually, we can go ahead and delete this other one
because I kind of forgot his password.
Okay.
And in this case, that's no problem.
We can simply delete users as we like
since we're only in development.
Okay?
Now we should be able to actually add this review.
And indeed, here we go.
Perfect.
So that wraps up this lecture.
All we need to do in the next one
is then create the factory functions
for getting one and getting all documents
of a certain resource.