00:02
- Great, so next let's go ahead and start working on our modules. We also need to be able to create, update, and delete those via our API as well. So within our terminal here,
00:12
let's go ahead and run node-ace make controller, put this inside of our API version one, and we'll call this our modules controller
00:20
and do hyphen a for the API only flag, so that we just get the methods that we care about there. Whilst we're within our route definitions, let's go ahead and add it in.
00:28
So router.resource, modules, and then we'll make use of our modules controller from our API version one folder.
00:38
We'll also take these as API only to exclude the show routes for the create data pages. Cool, so one thing to note about this, the way that we have this here,
00:48
we are doing the resource for the module completely separated from our courses. To make this a little bit more evident, let's go and jump back into our terminal, and I'm gonna have this take up the full screen here,
00:58
and let's do node-ace list routes. This is gonna list out all of the route definitions that we have defined inside of our application. The ones up at the top are gonna be our web routes.
01:07
So these are the routes for our web application as they're defined first. These are all listed in the order that we've defined them, and it's also the order that AdonisJS is going to use
01:17
to find a matching route per request. So it's gonna search from the top down in this list. Because we have our API routes defined after our web routes,
01:27
that means that they're all gonna be down here at the bottom. So right here, we have our course routes, and then just underneath it are the modules routes. That goes right to there.
01:37
Both sets have a specific ID route parameter on them, right? So our courses and modules both have an ID route parameter that they expect.
01:45
If for any reason we needed the course ID in addition to our modules ID, in most of the cases where we're getting a module ID,
01:54
we don't necessarily need that. We don't necessarily need to know which course the module applies to. However, for the two routes,
02:02
if we were to fulfill these with our API, not containing an ID route parameter for our modules, we would need to know which course ID we're after
02:11
to get those specific modules. Otherwise, we're gonna get all of the modules within our application for the organization, which would most likely not be what we're after
02:20
with our API. Additionally, in terms of our post, we also need to know which course to add the module into. Now we could do that with our post requests body data,
02:30
but if we wanted to keep things consistent with how we have it within our web application, you'll see that our modules are nested inside of our course ID for all of these. And that's how we're discerning which course
02:40
to add the module to as we post it up within our web application. So to keep that consistent with our API, what we'll wanna do is nest these modules
02:50
within our courses as well. So let's go ahead and jump back into our text editor within our route definitions. And we can easily do that using a resource here
03:00
by using a nested resource. So we just do that by doing courses. And now AdonisJS will nest the modules
03:07
inside of a courses resource for its route definitions. So if we save that, jump back into our terminal one more time and run node-ace-list-routes again,
03:17
you'll see that we have a slight difference. Now our module route definitions, they still have an ID route parameter, but they also have a course ID route parameter
03:27
that they expect as well. So that's gonna allow us to discern what course it is that we're looking to add the module to, get a list of modules for, and then for these ones,
03:36
they're not necessarily going to be needed, but for consistency sake, we will leave them there. So perfect. Let's go ahead and clear that out, jump back into our text editor here,
03:45
and let's walk through adding the create, update and delete operations for our modules. So in addition to our request for our store,
03:54
since we also need to get the courses ID, we'll accept in our params and then the organization, we will authorize our token for the create action
04:04
and pass the organization on in. Then we can go ahead and return our store module actions handle response.
04:13
And this accepts in the organization, course ID and data. So provide the course ID in first, which will come from our params, course ID,
04:23
and then we have our organization, and then we also need to get our validated data. So let's do that next.
04:29
Const data equals await request dot validate using, and we should have a module validator that we can use
04:37
that also needs our with organization metadata that will provide the organization ID into. So let's quickly take a look at our module validator real quick.
04:46
So this just takes in a name and a status ID, and then it's going to use our organization metadata to make sure that that status ID actually exists inside of the organization.
04:55
Our store module then is going to find the course, create the new module for the course, and then it's going to insert it
05:03
at the next available module ordering, which we have a separate method to simplify the use of that. Perfect. So that should all be a okay.
05:12
We're gonna move on down to our update, which will be very similar. So we also need our organization for that one, and we need to authorize the token
05:22
to allow updating for the organization there. Then we need to validate our data, which I remember to do first this time.
05:30
So we'll validate using our module validator with the organization metadata, and then pass the organization ID into there. And then we can go ahead and return back
05:40
the response of our updates module action, call the handle method there, pass the ID in as our params.id,
05:50
as all that we need to update is the module ID that we're looking to update. We can pretty much ignore the existence of the course ID route perimeter here,
05:58
and we'll pass in the organization and our validated data. Then we can jump on down to our destroy, and again, let's grab the organization,
06:06
authorize our token for deletion with the organization, await, and then we have a destroy module action
06:16
with the handle method that takes in the ID that we're looking to delete. So that's gonna be our params ID. Then this one also needs the course ID, and we'll talk about why here in a moment.
06:25
So we'll pass in our params course ID to that, and then we'll also pass the organization in. Before we talk about that real quick,
06:32
let's grab our response as well, so that we can return back our response with a status of 204.
06:42
Now, alternatively to setting the status manually here, there's also helper methods on the response in case you weren't aware. So we could call no content to return back a 204 that way,
06:52
if you prefer a little bit more of a verbal representation of what a 204 would look like. For consistency sake, I'm gonna go ahead and leave this as a status of 204.
07:01
Typically what I do within my applications is have an HTTP status const or enum that I use throughout the application so that I can reach for a specific status that way.
07:11
But hard coding works just fine as well. Now, okay, so for our destroy module, let's go and dive into there. The reason that we need the course ID is because we're actually going to query the course
07:20
for the ID that we're providing. And with that course, we're going to decrement the ordering of our modules
07:28
for any module that is beyond the one that we're deleting. So for example, if we have module one, two, three, four,
07:36
and five, and we delete number three, what this right here will do is decrement four and five so that they become three and four,
07:45
keeping our ordering up to date in that sense. So in order to do that, we do need to know what the actual course's ID is within the action there. All right, so perfect.
07:55
That should get all three of those good to go. While we're here, we can go ahead and also add in the tag. So async tag, that takes in params,
08:05
request and our organization from the HTTP context. We need to authorize our token to allow updates with our organization.
08:15
We need to validate our data. So await, request, validate using, and we should have a module patch tag validator similar to how we have with our courses
08:25
that needs the with organization metadata to ensure that those tags actually exist inside of the organization we're dealing with.
08:31
And then we have an await update module tag action that we can call the handle method for,
08:38
pass in the ID of the module that we're updating, the organization, as well as the validated data. Just like with our courses,
08:46
I believe that this should return back our updated module, which it does. So we can go ahead and just return directly back there as well. Again, this tag one is not going to come predefined
08:56
with our resources. So we need to mimic that route definition with a separate route definition as well. So do another patch down here,
09:04
slash courses slash, and we'll do our course ID route parameter,
09:11
slash modules, slash the module ID, slash tag, mimicking the nested resource route identifier
09:20
that we have going on for our modules. Then this will use our modules controller and its tag method.
09:27
And we give it the name of as courses.modules.tag. Again, mimicking the courses.modules resource that we have going on for the naming convention up there.
09:37
Perfect. All right, so let's give that a save, hop on back, give it a hopscotch. And just as we did previously, I'm going to go ahead and just duplicate
09:44
our courses collection here by right-clicking, duplicate. And then I'm going to go through and just update all of the names here real quick. I won't drag you along for that
09:54
so that they all reference modules instead of courses. All right, so I've got that done. Let's first test out our store modules. So for our route identifier,
10:04
what we're going to want to do is specify the course that we're after. So we do a course ID of one. So we'll just focus specifically on one here.
10:12
And then we'll want to target the modules within that course for our body. What we need is a name and a status ID. So we can get rid of our access level and difficulty.
10:22
And this I believe would be module number three within our first course. So let's go ahead and try and create that.
10:31
And whoops, I left a dangling comma there. So let's go and get rid of that and try that one more time. And perfect, okay, good. So we got back our module three with a status ID of three,
10:40
put into course number one with an order of three as it's the third module in the course. If we were to do a module four, send that off,
10:50
we get back module four, again, with a status ID of three with an order of four, since it's now the fourth module inside of course number one. Great, so I'm going to note that one has an ID of four.
11:00
We'll use that for our deletion. So we'll go ahead and give that a save. Let's jump on down to delete next while I have that ID in memory.
11:09
So we'll want to target course number one, it's modules and the specific ID of four for our modules. We'll leave the HTTP method as delete. We don't need to send up a body.
11:19
So let's go ahead and try sending that off. And perfect, we get back our 204 no content response. So that worked a-okay. Go ahead and give that one there a save. Next for our update,
11:29
we need to switch the URL structure here one more time. So course ID of one, modules, we should have a three since four was the second one that we created.
11:39
And then for our body, again, we just need a name and a status ID so we can get rid of our access level and difficulty there. Let's try switching the status ID to two.
11:48
We need to get rid of our dangling comma and we'll switch the name to module three edit. All right, let's try sending that off. And perfect, that worked a-okay.
11:58
Our name's now module three edit with a status ID of two instead of three. So we can give that a save. And then we have our patch module tag request
12:08
that we need to hone in on module number three with. And then inside of the body, we can, let's try switching the status ID to one
12:16
instead of what we had previously switched it to two. And we get back a 404 not found because it cannot find the route that we have sent the request for.
12:25
If you'll note, we did module not modules. So let's tack an S on there and try that one more time. There we go. Okay, good, that looks good. So now we get back our module three edit
12:35
and the status ID for that has now switched to one rather than two. If we go ahead and try switching that back to three, send that off, it's now three. So perfect.
12:45
Furthermore, with our modules, they don't have access levels or difficulty IDs. So if we were to try and update either one of those, so difficulty ID, send that off,
12:55
we're gonna get back a validation error because the status ID field must be defined. If we provide a status ID in addition to that, so status ID of two,
13:05
our validator will just strip out the difficulty ID and our actual controller will never see it. So we'll just get back the status ID from that. So this should succeed, which we see it does.
13:15
We get our status ID of two and our controller never sees this difficulty ID because our validator has stripped it out. So awesome, that is all working A-okay. Let's go and give that a save.