‫In this video,
‫we're gonna be building a handler factory function
‫in order to delete review documents,
‫but also documents from all the other collections,
‫all with one simple function.
‫So, as I mentioned right at the beginning of this section,
‫adding very similar handlers to all of our controllers
‫will create a lot of duplicate code, right?
‫Because all these update handlers,
‫or all these delete handlers,
‫or all these create handlers,
‫they really all just look basically the same, right?
‫Also, imagine that we wanted to change
‫like some https status code or status message.
‫Then we would have to go into each and every controller
‫and then change all the handlers in there.
‫And so, instead of manually writing all these handlers,
‫why not simply create a factory function
‫that's gonna return these handlers for us?
‫So, a factory function is exactly that.
‫It's a function that returns another function,
‫and in this case our handler function.
‫So, for deleting, for creating, for updating,
‫and also for reading resources.
‫Okay and I know that this whole concept can be a bit complex
‫to wrap your head around,
‫and that's the reason why I left this
‫for the later part of this course.
‫But now, I believe that you're actually ready
‫to implement this kinda stuff.
‫So this kind of logic is what every advanced
‫JavaScript developer should be able to implement,
‫and so again I believe that at this point in the course
‫you're really ready to start using advanced concept
‫like this, all right.
‫But enough talk, let me now show you how it actually works
‫by using the delete handler as a first example.
‫And so actually we have one in the tour controller,
‫and so let's go ahead and copy that one,
‫so delete tour.
‫Okay, so I copied it basically
‫as a template for us to follow.
‫So let's create a new file, and I'm going to do that
‫in the controllers.
‫All right,
‫so handler...
‫factory.js.
‫And I'm doing this is the controllers folder,
‫well because the functions that we're gonna write here
‫will basically return controllers.
‫And so for me it makes a lot of sense
‫that you put them here.
‫So let's just copy this part here,
‫just to keep it as a reference.
‫So again the goal here is to basically create a function,
‫which will then return a function
‫that looks like this one here.
‫But of course not only for the tour,
‫but for every single model that we have in our application
‫and that we might have in the future.
‫So this function needs to be prepared for that,
‫and so what that means is that inside the factory function,
‫we will pass in the model, all right.
‫So let's call this one deleteOne.
‫And it's called like this, again,
‫because this function is not only going
‫to work to delete tours,
‫but also to delete reviews and users
‫and in the future some other documents
‫that we might also have.
‫So as I was saying in the beginning,
‫we will pass the model into this function.
‫So we pass the model and then we create a new function,
‫and that function will right away
‫then return our async function,
‫so basically all of this or async handler function.
‫Okay, and so now all we need to do is to actually change
‫from the specific tool model to the more generic model.
‫Then here we will also change this from tour to the document
‫because again, we will not know what kinda document is this.
‫So this function will not really know if it is a tour,
‫or if it is a review, or a user.
‫And so we need to take the tour out of all of this,
‫and that's actually it.
‫So this basically the generalization
‫of this specific function, which worked only for tours,
‫and now this new one works for every model.
‫What we also need to do here is to import this catchAsync
‫and also this AppError.
‫So catchAsync...
‫and I believe it's in the utilities folder.
‫And then, not AppError but catchAsync.
‫Then duplicate this here,
‫AppError, and this here is uppercase.
‫Give it a save, and we're now ready
‫to actually test this out.
‫So this is how it's going to work,
‫first of all we need to import that handler factory.
‫And so let's say,
‫and I'm simply going to call it factory here.
‫So require, and it's in the same folder,
‫so handler factory.
‫All right and so let's comment this one here out,
‫or actually not all of this.
‫Yeah or actually we can comment it out,
‫and so the new exports.deletes tour will be...
‫factory.deleteOne and then pass in the model,
‫which is tour.
‫And that's it, that's all we need to do.
‫So just to recap very quickly here,
‫so we call this deleteOne function,
‫then in there we pass the model,
‫and so what's going to happen is that this function
‫will then right away return this handler function
‫that we had before.
‫Simply the specific model, which before was the tour,
‫is now going to be replaced with the one
‫that we passed into the function.
‫And by the way this works because of JavaScript closures,
‫which is just a fancy way of saying
‫that this inner function here will get access
‫to the variables of the outer function
‫even after the outer has already returned.
‫So calling this function here
‫will then return another function,
‫which will then sit here and wait until it is finally called
‫as soon as we hit the corresponding route.
‫And so let's now try exactly that.
‫So delete tour,
‫okay, and let's choose a tour
‫that we don't really need here for now.
‫So let's say...
‫now let's say here The Snow Adventurer
‫'cause it also doesn't have any reviews.
‫So let's send that,
‫oh and now we don't have permission to preform the action,
‫and that's because we're not logged in as an admin.
‫So let's try that,
‫and so this is the admin that we need to be logged in.
‫Okay, so that's done.
‫And so now this should work, and indeed it did work.
‫And so that's proof that our factory function
‫is really doing it's job.
‫Okay 'cause if you now come back here,
‫we had 10 results and so now we should only get nine,
‫so perfect.
‫And now the goal is to be able to use this
‫in each and every single controller.
‫So let's copy this here
‫and go to the reviews.
‫Oh and of course we need it up here,
‫right in the beginning, now right,
‫and so now export.deleteReview
‫is equal to factory.deleteOne
‫with the review model.
‫And that's it, that's all we need to do
‫in order to implement the delete handler.
‫Now of course we also need to specify the route handler.
‫Now of course we need to specify the route itself,
‫and so let's do that here as well.
‫So router.route
‫because here we actually need the ID parameter.
‫And now delete is simply reviewController.deleteReview,
‫and I'm not messing with the permission here,
‫neither with authentication
‫because for now I just want to make this work
‫and worry about that stuff a bit later in this section.
‫Okay, so let's close this stuff up here.
‫So get all reviews,
‫all right,
‫let's save this and this one as well.
‫So that now we can start with a blank sheet here
‫and let's just start by getting all reviews,
‫so that we can now delete one.
‫And so let's delete, well just this one.
‫Okay, now we also need of course this,
‫and then the delete http method.
‫We need no authorization at this point,
‫so let's just send it.
‫And indeed no content, so 204.
‫And if we now get all the reviews,
‫then we should be back to having just three.
‫Yep, that works and so let's move on to the next one.
‫Okay so reviews, reviews.
‫Let's get this line of code here and now finally add it
‫to the user controller as well.
‫All right, and of course all of this,
‫I understand it's a bit confusing now messing
‫with all of these different files,
‫but we just need to do it once and then we're done
‫with all that confusion.
‫So here we already had the export.deleteUser,
‫now all we need to do is to then call our factory function,
‫so deleteOne and then the user.
‫Now only the administrator should later be able
‫to actually delete users because remember that
‫when the user deletes himself,
‫then they will not actually get deleted
‫but only active will be set to false.
‫But the administrator on the other hand
‫is really gonna be able to delete the user effectively
‫from the database.
‫But again, we're going to worry
‫about that permission stuff a bit later.
‫For now, let's check in the userRoutes
‫if the route is actually implemented,
‫and yeah it is down here.
‫And so since we now implemented this,
‫let's also test it here again also on Postman.
‫So first let's save this one.
‫So...
‫delete review,
‫and now let's simply copy this
‫into yet another route.
‫So delete and then one user,
‫but I'm actually not really going to do it now.
‫All I want is to just get some random ID.
‫Or actually let's just create a new user,
‫so basically sign up, and then delete that one right away.
‫So hello, like this.
‫Get all users, and then it's this guy here.
‫And so let's delete him right away,
‫so we send, we get 204 no content.
‫And of course, now he should be gone.
‫Now if we try to see her again,
‫so basically trying to delete a user
‫that is no longer there, we should get an error.
‫So let's take a look, and indeed no document found
‫with that ID.
‫And so this means that in our factory function,
‫so right here, all of this the AppError and the catchAsync,
‫all of that is still intact.
‫So everything still works just the same as before.
‫Now so that was also important to test here.
‫Let's just quickly save this here as well,
‫so each and every single endpoint that we're implementing,
‫I'm also adding it here into Postman
‫because a bit later we will then actually be able
‫to actually create some API documentation
‫based on all of this that we have saved here in Postman.
‫So that's yet another handy feature of this application.
‫So we have delete the current user,
‫and again that's different from just deleting the user
‫because this one here is for administration
‫and this one is for the currently logged in user,
‫so very different.
‫Okay, so this was our first factory function
‫only for deleting and only for you to understand
‫the concept itself.
‫Next up, we're then gonna implement factory functions
‫for updating and for creating documents.