Instructor: All right, in this lecture,
we're going to talk about something called
nested routes, what they are,
why we need them, and how we can
actually implement them in Express.
Let's think for a second how in practice,
we actually want to create a new review.
Up until this point, when creating new reviews,
we always manually passed the tour ID
and the user ID into the request body,
and then created the review from there, right.
That's okay during development, but of course,
that's not how a review will
be created in the real world.
So, in the real world, the user ID
should ideally come from the currently logged in user
and a tour ID should come from the current tour.
That should ideally be encoded
right in the route, so in the URL.
When submitting a post request for a new review,
we will want to submit that to a URL like this.
Let's write that down here just as a comment.
Ideally, we will want to do a request
for post, for tour, and the ID of the tour,
it doesn't really matter here, and then reviews.
Okay, so now, just like this,
we have the tour ID right in the URL
and the user ID will then also come
from the currently logged in user.
What we see here is now a so-called nested route.
They make a lot of sense when there is
a clear parent-child relationship between resources.
That is clearly the case here, right.
Reviews is clearly a child of tour.
This nested route basically means
to access the reviews resource
on the tour's resource, all right.
In the same way, we will actually also want to
access reviews from a certain tour in the same way.
Let's say then a get request,
and again for tour slash tour ID and slash reviews.
This would then ideally get us
all the reviews for this tour.
We could go even further
and also specify the ID of the review.
So again, just a random string here,
but you get the point.
In this case, we would get review
with the ID of this here
on the tour with this ID.
This is what nested routes are all about.
This is a way more easier way of reading
and understanding how the API works for our API users.
It's way easier then messing around with
query strings and all that stuff like that.
Also, it really shows how there is
this clear relationship between these resources,
again, reviews and tours.
All right, but enough talk.
Let's now actually implement this
starting with the post route.
Now, since the route actually starts with tours,
it will be of course redirected to our tour router.
We're going to have to implement this functionality
at least for now, in the tour router,
even though that seems a bit counter-intuitive
since we're in fact, dealing with reviews.
But again, for now, let's implement it like this.
We come to our user router
and first, since we're actually
going to use reviews here,
we need to import the review controller.
Controller require.
Maybe I should have just copied the line from before.
Controllers, and review controller.
All right, now here at the very bottom,
and let's actually get our code
for this example from here
just as a reference.
So that we can now actually implement it.
The route that we're going to implement here is
slash ID and then reviews.
This tour part here, as you already know,
is where we mounted this router
and so therefore, we do not have to repeat it here.
But then, we have the tour ID and then slash reviews.
In order to make this really clear,
let's actually call it tour ID
since we're now dealing with
different resources here.
So it's a bit clearer to really call it what it is.
We now want to implement the create review.
Authcontroller dot protect.
We also want to restrict access only to users,
and then of course, our review controller dot create
review, all right.
Again, it is a bit weird and counter-intuitive
to actually call the review controller
here in the user route.
Well actually, it should not be in the user route.
For some reason, I opened the user routes
and not the tour routes, so sorry for that one.
Let's cut it from here, come to our tour routes,
and actually do it here at the bottom.
Of course we also need to get the review controller.
So now we should be good to go.
That was a stupid bug.
But anyway, what I was saying is that
it doesn't make much sense to actually call
the review controller in the tour route,
but again, for now, we need to do it like this
because the route starts with tour.
It's this router that will get activated.
In the next video, we're going to fix that,
but for now, we just want to make it work
and to become familiar with
this whole concept of nested routes.
Anyway, we now got our tour ID right in the route,
but of course, we need to let
the controller know that it should now use this tour ID
and also the currently logged in user's ID.
We now need to go ahead
and update our review controller
right here at create review.
What we're going to do is this.
We will say, if there is no request dot body
dot tour, so basically if we didn't specify
the tour ID and the body,
then we want to define that
as the one coming from the URL.
Req dot body dot tour equals request,
and now remember how that URL parameter
is on request dot params and then of course,
the name of the parameter itself, so tour ID.
This is the first part and second,
we also need to do the same with the user.
If there is no request dot user,
or actually, request dot body dot user,
well then the request dot body dot user
should be request dot user dot ID.
And again, we get request dot user from
the protect middleware, and that's actually it.
Let's just put a comment here, nested routes.
With this, we actually make it so
that the user can still specify manually
the tour and the user ID.
What we're doing here is simply
to define them when they are not there
or when they are not specified in the request body.
This should be enough for us to test this now.
All right, so let's take a look
at the users that we got at this point.
We have these two regular users,
we have the test user and we have Jonas here,
but we forgot his password.
Let's go ahead and delete this user
and create a new one.
All right, so in Compass, the users,
and it's this one.
Let's recreate this user basically.
All we really need is these two pieces of data.
Actually that's sign up.
The same name, the same email
and the same password as well.
At this point, we are already logged in as this user,
so-called Jonas, let's keep that in mind.
Next up, we need to choose which tour
we actually want to create the review on.
Let's again do it here at The Forest Hiker
so that then we get multiple reviews on the same tour.
What we're going to now
is to basically access that nested route
that we just created.
We have the tours.
Now we need to get the tour ID,
and again, we're going to use this one
for The Forest Hiker,
and then slash reviews,
and then remember a post.
Then we also need to specify the authorization,
so bearer token, and then now in the body,
all we really need is to
specify the rating and the review.
The rating is five
and then some text here.
So this should actually already be enough to try this out.
Let's send it.
Now we don't have permission to perform this action,
for some reason, so that's weird.
We signed up as this Jonas,
and it's actually just a normal user
like it's supposed to be.
Let's take a look at our router.
Here, oh okay, it's user, not users.
A small bug like that can, as you see,
crash this entire route, so let's try it again now.
And now we actually get the final review
with both the tour and the user correctly defined.
At least I hope so.
The tour ID, you see, ends here in 951,
and so it's exactly the same here.
The user is this 1f3, and so indeed,
it is this exact same one.
All right, and so now we should actually be able
to confirm that, and so this get tour here
is actually already the one that we were
creating the new review on.
Let's take a look, and indeed,
we now get two reviews.
This one is the one that we just created.
It is on the correct tour and of course,
also the correct user with the name of Jonas.
Awesome, that's really cool.
Let's go ahead and save this.
I'm going to create a new folder here again.
I'm going to call it tours slash reviews.
Now in here, let's create,
create new review on tour.
That should actually be outside and just like this.
Let's actually put that one here.
It doesn't really work as it should for some reason.
And here we go.
All right, that worked just fine,
but as I mentioned before, the implementation
is a bit confusing at this point.
And again, that is because we technically defined
a review route in the tour router.
That's a bit confusing, and so in the next video,
we are going to fix that.