00:01
now we need to fill out our models with the columns and relationships that we have inside of our migrations. To make sure that we hit all of our column names, we're gonna leave our migrations open on the left-hand side
00:11
and we'll fill out our models on the right-hand side. So within our users here, let's scroll up to our models, click on your user model there and drag it over to the right-hand side. And that's gonna put that user model side-by-side
00:20
with the user migration. And for our users, we're rolling with the default. So we have our columns and relationships that we have inside of our migrations. For our users, we're rolling with the default.
00:29
So we have our columns already a one-to-one match between our migration and model, but we do need to add in our relationships for the user as well. And the user relates to its email histories,
00:38
its password reset token, as well as organizations as a whole. The first two are gonna be has many relationships. So we'll wanna do an has many decorator and provide in a callback
00:48
that returns back the model of the relationship. So that's gonna be our email history model. Then we'll declare a property for this email histories with the type has many
00:58
and we'll import that with a type of email history using our model there. Now you'll notice that we have a red squiggly on our has many type here.
01:07
If we hover over that, we're gonna see a type referenced in a decorator signature must be imported with import type or a namespace import when isolated modules and emit decorator metadata
01:17
are enabled, which AdonisJS does use. So all that to say, what we wanna do is scroll up to that import where we have it right here and switch that from importing this as actual code
01:27
to importing just the type. So that whenever this is built and it's converted from TypeScript to JavaScript, TypeScript will still be able to do its check because it'll have a reference to the type,
01:36
but then the final build will be able to omit this import altogether because the type won't be necessary at that point in time. Okay, let's scroll back down now
01:44
because we also need to add in our password reset token. So we have another has many there pointing to our password reset token model,
01:53
declare password reset tokens as many type of password reset token. And then lastly, a user needs to relate to its organization.
02:02
And this is a many-to-many, we have a pivot table for it. So we'll want to use the many-to-many decorator and point it to our organization model. Now for this one, we are not using defaults.
02:12
So we will wanna add in column options for this. First, we want to change the pivot table name that'll be used. By default, AdonisJS will alphabetically sort
02:21
the two models between the relationships. So our organization and user models, and we'll convert those to snake case. So by default, this would look for organization user, but we've defined our pivot table name
02:31
as organization users, which is why we'll want to manually define the pivot table to use for this relationship. Then whenever we query this relationship,
02:40
we also want a pivot column with the role ID to always be included. So we'll go ahead and define that pivot column for this many-to-many relationship as well.
02:49
Okay, let's declare a property name for that as organizations and set the type to many-to-many type of organization. And you'll notice that we didn't get a red squiggly
02:59
on the many-to-many whenever we imported that. And that's because it imported it in the same import statement as our has many. So it already has that type added on there and we don't need to worry about it.
03:09
And whenever we save, it'll add a comma on there to fix red squiggly that we had right there. Okay, so there is our users migration and model all ready to go. We're just gonna go through the same order
03:19
that we have inside of our migrations using that as the order that we go through things. So we'll jump into our roles next, open that here on the left-hand side of our text editor. And then we'll jump into our role model.
03:29
So role model over there. And for this one, we just have a name column. So we'll add in a column, declare name, type string. And this is defined in our organization users pivot table.
03:39
So we don't have any relationships that are defined for this model. In fact, if you didn't want a model for your roles, you really wouldn't need one because you would just be working with it for the most part via that many-to-many relationship.
03:49
But we'll go ahead and add this one here as that'll help with our seeding when we get to it. All right, so we're done with our roles now. We don't have any relationships for that. So we're good to jump down to our organizations next
03:58
and command P and jump into our organization model. All right, we have a name column. So column, declare name, string and quite a lot relates back to our organization.
04:08
So we're gonna have a number of relationships that are defined here. First, an organization has many courses. So we'll do a has many there. Point back to our course model,
04:17
declare courses and use the type has many, type of course. Now, if you don't want to scroll back up to the top of your file and manually add in type at the import there,
04:27
what you can do is just go over to the red squiggly, hit command dot, and that will open up a quick fix panel. And of the quick fix options that we have here, we wanna use import type.
04:36
So we'll go ahead and hit enter on that one and you'll see that automatically added that import type in for us. So there's another approach on how you can get that in. Now let's go ahead and copy this has many
04:45
and let's paste it in five more times. So one, two, three, four, and five. And we'll just work on the decorators here to fill out what these are going to end up being.
04:54
So first, we also have our modules. Now, whenever you import this, be careful because it will try to import from Node.js module. Instead, we wanna scroll down to our model import
05:04
and use that one instead. Okay, then we have our lesson, import that, our access level, import that one, our difficulty, that one.
05:14
And then lastly, our status. Then we can go through each of those has many and just copy its value and paste it into the type of, just kind of like what we're doing here.
05:22
That in, copy, paste, and then switch the property name. So for this one, we'll wanna use modules. All of these are has many, so we'll make sure that they are plural. So this one will be lessons.
05:32
Then we have access levels, difficulties. And lastly, our statuses. Oh, I missed one. We have one more has many, so let's give that a copy and a paste.
05:41
These are our organization invites. So we'll do our organization invite model there, organization invite model there. And then we just call this property invites.
05:51
Since we're on our organization model, we can infer that organization is gonna be assumed. So we'll just simplify our name there a little bit. And then lastly, we have our many to many relationship
06:01
to our users. So import our user model there, declare users many to many type of user. And then we also need to specify the same alterations
06:11
that we did on our users model. So pivot table, organization underscore users. And then we'll include the pivot column rule ID
06:20
anytime that we query from this as well. Okay, there's our organizations. We'll move on to organizations users is our pivot table. So we don't need to worry about a model for that one.
06:29
So we have our access levels next. Jump into our access level model there. So we have our organization ID as a column. So declare organization ID of type number.
06:39
We have a name, so column, declare name, type string. And we have a color, column, declare color, type string.
06:48
An order, column, declare order, type number. And that is default column. Declare is default of type boolean. As for our relationships,
06:58
this will relate back to our courses and our lessons. And an access level can belong to multiple of them. So we'll use has many here and provide an callback for our course model.
07:08
Declare courses has many import that and hit command dot and import just the type, type of course there.
07:17
We can give that one there a copy, paste, scroll down a little bit here and switch this to lesson, lessons, and then lesson in the type of there as well. And we are done with our access level.
07:27
Now, the nice part here that's gonna save us a little bit of time is our access level difficulty and statuses are all the exact same. If we go through the migrations for them. So here's our access level.
07:37
For now we jump into our difficulty and our status. You'll notice nothing changed between these three. So we can simply just copy the entire contents of our access level.
07:46
We'll leave the class name out of the equation here and just copy the contents. We can now jump into our difficulty model just like so and replace all of its contents with what we have copied.
07:56
So just paste that in, hit command dot on one of the red squigglies, add all missing imports. And then lastly, we just need to switch the has many import there to an import type.
08:06
Do that one more time with our status model. Go down to the contents and replace it all. Command dot on a red squiggly, add all missing imports.
08:14
And then go over to our has many and use import type. Cool, so there's those all ready to go. Now we have our courses next. And I'm actually gonna use our access level. Copy there is a good starting point
08:24
for our course model as well. So I'm just gonna come down to here and paste everything in from our access level copy. I'm gonna hold off on the import because our relationships will change a little bit.
08:34
And I am just noticing that we missed our organization import. So belongs to organization,
08:40
declare organization belongs to type of organization. Okay, go over there, command dot. All right, let's give that line there a copy. And let's go back to our status,
08:50
paste it in because we also need it there. Command dot, add all missing imports. Go back to our difficulty. And I'll explain why we need this here momentarily. Paste it in here, command dot, add all missing imports.
09:00
And then our access level paste as well. Command dot, add all missing imports. And this is a belongs to because generally whenever the ID column is on the model that you're working with,
09:09
the model itself is going to belong to the relationship of the ID column. So our access level belongs to the organization
09:17
because it's specifying the organization ID on the access level. We can think of the organization as the parent and the access level as a child to that organization in that sense.
09:27
Therefore it belongs to it, which is why we define this as a plus two rather than a has one. All right, so we were on, what model were we on, our course? Yep, okay.
09:37
So in addition to our organization ID, we also have an access level difficulty and status ID. So we'll do a column, declare access level ID,
09:46
type number, column, declare difficulty ID, type number, and column, declare status ID, up type. And we have a name,
09:56
and then we also have a notes rather than a color. So notes, and we'll make that nullable and we can leave the order as is because this one also has an order. If we scroll down now to our relationships,
10:06
where we've left our red squigglies, just like we went over with our organization, we have multiple ID columns on our course for access level, difficulty, and status ID in addition to our organization.
10:16
So all three of these relationships are also going to be belongs to on our course model. So we'll want to scroll down and we can switch this one here to a belongs to,
10:25
switch this from our course to our access level model, belongs to, point that to our access level model, and this will be our access level. We can go ahead and fix this red squiggly now,
10:35
so we'll hit command dot and use import type there. We'll go ahead and copy this belongs to for access level, paste it in twice for our difficulty and status,
10:43
switch this belongs to to our difficulty model, and switch this one to our status model. Give that status there a copy, paste it into the type of,
10:52
give difficulty a copy, paste it into the type of, and switch the name to difficulty and status, our status there. Now, in terms of our has many,
11:01
rather than having many lessons, we're instead going to have many modules. So we'll import our module model there, and then use it in the type of,
11:10
include the import for our has as well, and then switch this to a module. We aren't going to have many lessons because if we take a look at our lesson migration really quick,
11:20
you'll see that it only relates to our module and not the actual course. So we don't have a course ID in there. So instead, what we're going to have it do
11:27
is reach from our course through our models to a lesson so that we can still query our lessons specifically from our courses. And for that, we're going to use
11:36
a has many through relationship definition, which we can use because it's has many on both sides. Our course has many modules and our modules has many lessons.
11:45
So we'll do at has many through, and rather than accepting in one model here, it accepts in an array of two models. The first one is going to be the endpoint of the relationship.
11:55
So that's going to be our lesson model. And then the second one is going to be the intermediary model, which is our module model. Beyond that, all we need to do now
12:04
is declare our property of lessons has many through type of, and point it to our lesson model. And now directly from our courses,
12:13
we're going to be able to query our lessons bound to that course through its modules. And we're now done with our courses. So next up, we have our modules over here,
12:22
and I'm going to use our course as a starting point for our module. So I'm going to give everything inside of our course class here with our copy. We can jump into our module model
12:31
and replace all the contents of this one with our course model. We'll wait to add our imports here until we've fixed everything up. So to start with, our modules don't have an access level
12:41
and they don't have a difficulty. So we can get rid of those two. It does have a status. It does have a name. It does have notes and it does have an order. It does not, however, have an is default flag. Actually, our course doesn't have that either.
12:51
So we can jump back over to our course and get rid of that. There we go. Okay, back to our module. And now we're ready to take a look at our relationships.
12:58
So a module relates back to a course, a status, and a lesson. So although it relates back to lessons, we're not going to want to use a has many through for that. Instead, it's going to be a has many. So we'll leave our modules there
13:08
and then we will also leave our status and we'll get rid of our access level and difficulty relationship definitions there. And now that we have this honed in on what we're specifically wanting to use,
13:18
we're going to go ahead and hit command dot, add all missing imports, go over to our belongs to there and use import type on those. So our organization and status relationships are good.
13:28
We just need to switch our module to now point to our lesson. Lessons and lesson one more time. And there we go. Now we're done with our module and ready to move on to our lesson model.
13:37
Let's jump into our lesson model over here and let's go copy our course one more time down through our modules. We can omit lessons and copy up through the ID and then replace all of the contents
13:47
that we have so far inside our lesson there. Again, let's fix up the columns before we go to the relationships. So we have an organization ID. We have an access level. We do not have a difficulty on our lessons.
13:57
So we'll get rid of that one, but we do have a status. We do have a name. We do have notes. We do have an order and we do have one additional date time. So we'll add in a column dot date time there.
14:07
We'll leave out the options and declare this as our publish at with a type of date time or null as it is nullable.
14:16
Okay, scroll down now to our relationships. We do not have a difficulty on our lessons. We can get rid of that one, but we do have these other three organization access level and status.
14:25
So we'll leave those as is. And then rather than being a has many modules, it now belongs to a module. So we'll import our belongs to there.
14:34
We will import our module model. So I want to go down to the specific model import and import that. Go to our has many and switch that to a belongs to
14:44
command dot on that to switch it to an import type. And now we can go up to our status command dot and add all missing imports. Cool. We're done with lesson.
14:52
Now we're on to our email histories and I think these remaining three here are going to be pretty unique to one another. So we probably won't be copying and pasting like we have been. So for this one,
15:01
we're going to have a column declare user ID of type number and then a column declare email old of type
15:10
that one's a string not a number and then a column declare email new of type string. And then since we have a user ID on this model, it will belong to a user.
15:20
So we'll add in belongs to point that to our user model declare user belongs to command dot use import type type of user
15:30
and we're now good to go on our email history, which takes us now to our organization invites. So organization invite model there.
15:39
Okay, so we have a column declare organization ID of type number.
15:44
We have a column declare invited by user ID of type number.
15:52
This is the ID of the user who sent out the invitation and then we also have a column declare canceled by user ID number
16:02
and I believe that one's nullable. So scroll over the firm that yep sure is and if an invitation has been canceled, this will be the ID of the user who canceled the invitation. Then we have a role ID.
16:12
So column declare role ID of type number. This will be the desired role for the user that we're sending the invite to
16:21
and then we need the email of the user who should receive the invitation. So declare email screen and then we have some nullable date times.
16:30
So column dot date time declare accepted at is date time or null and we go ahead and give this here a copy and paste it one more time
16:40
switching the column name to canceled. So if an invitation has not been accepted, accepted at will be null. If it has been accepted, then we'll have some date there to flag that as truth.
16:50
Same thing with our canceled. If an invitation has not been canceled, then this will be null. If an invitation has been canceled though, this will have a date time value and we'll be able to determine that as such.
17:00
All right, then we have our relationship all four of which are going to be a belongs to. So belongs to first up we have organization,
17:08
declare organization belongs to type of organization. Go over to the bus to their command dot import type. There we go.
17:16
Give that a copy and let's scroll down a little bit here and paste this in three more times. This first one that we pasted in will be for our user.
17:24
This second one that we pasted in will also be for our user and this third one will be for our role. So we could point that to our role model. Okay, let's go ahead and copy the names
17:33
and paste them into the type of just like so. This first one for our user is going to be the invited by user, the user who sent the invitation.
17:43
Then we have the canceled by user, the user who canceled the invitation. And then lastly, we have the role. Now by default, these two user relationships
17:52
will try to look for a user ID column on this model and we don't have one of those. So we want to specify the foreign key that this should look for. So we'll do foreign key there.
18:02
And for the invited by user, we want to read from the invited by user ID column for its value. And for our canceled by user,
18:10
we want to use a foreign key of canceled by user ID. All right, one more migration and model here to go. We have our password reset tokens.
18:20
So password reset token model there. All right, we have our user ID. So column, declare user ID, type number,
18:28
and then we have the token value. So declare value of type string. Looks like we have one more date time there as well. So we do column dot date time
18:38
with a property name of expires of type date time. Okay, and then since the user ID is on this model,
18:46
we can infer that it belongs to a user. So we use at belongs to providing our user model there.
18:52
Declare user belongs to type of user. Go return belongs to command dot import there. And then switch it to import type.
19:02
All right, we are now done. We have all of our models defined along with the relationships. So we're ready to move forward.