In this lesson, we'll delve into AdonisJS Models learning what they are, what they represent, how to create them, what we can do with them, and more.

🕑 Chapters:

00:00 - What Is A Model?
00:40 - Database Query vs Model Query
02:30 - Model Creation Flags
03:35 - Model Features
04:50 - Creating Our First Model
07:00 - Column Decorator Arguments
08:37 - Default Column Naming Convention
10:15 - Converting Migrations To Models
12:20 - Outro


📜 Transcript:

0:00

with adonisjs there's two different ways

0:01

we can actually communicate with our

0:02

database so you have the database module

0:04

and then you have models now models

0:06

serve as the recommended interface to

0:07

actually communicate with your database

0:08

and then falling back to the database

0:10

module anytime that models can't fill

0:12

the void that you're looking for now

0:13

models follow the active record pattern

0:15

meaning that they're going to serve as

0:16

encapsulations for the database

0:17

interactions that we'll be doing and

0:19

they'll provide back objects or classes

0:21

that are type safe for us so a model is

0:23

going to serve as a representation of an

0:25

actual database table so for the most

0:27

part we're going to want one model per

0:28

table within our database with the

0:30

exception of those many to many pivot

0:31

tables in the long run by utilizing

0:33

these models we're actually going to

0:34

save ourselves a ton of code so if we

0:36

actually take a look here adonisjs has

0:37

an example on their documentation here

0:39

so here's an example of what a query

0:41

looks like without models so you query

0:43

it from the database using the database

0:45

module and then you represent what table

0:46

you want to pick from selecting The

0:48

Columns then you get back all of those

0:50

users then anytime that you query those

0:51

users for display you're going to need

0:52

to Loop over them to convert any

0:54

database values to display safe values

0:56

so in this example here they're looping

0:58

over the users getting a single user

0:59

within this call back here then they're

1:01

converting that user's date of birth

1:02

using luxem date time they're ingesting

1:05

that date of birth and then changing its

1:06

format with models this is vastly

1:08

simplified and we only need to perform

1:09

this conversion once and adonisjs will

1:11

recognize we want to do that every

1:13

single time so if we actually take a

1:15

look at their example here we have a

1:16

user model which is represented by a

1:18

class that extends a base model in this

1:20

column decorator represents the actual

1:21

property that is decorating is a valid

1:24

column within our database table off of

1:26

the column decorator we're chaining off

1:27

a date method the State method actually

1:29

instructs Lucid to actually take that

1:31

value convert it from that date or date

1:33

time string from the database and

1:34

convert it into a lux and date time

1:36

object for us automatically no

1:38

additional checks needed on our part now

1:39

within the State method we're actually

1:41

providing an option to serialize the

1:43

serialize method will run anytime that

1:44

our user model is actually serialized so

1:47

really anytime that we're passing it

1:48

from Adonis to outside the Adonis

1:50

ecosystem this could be returning it as

1:51

an API response or it could be returning

1:53

it from Edge to our front end code base

1:55

and down here they do have an example of

1:57

how to actually go about serializing

1:59

this manually as well but this method

2:00

will run anytime that that happens and

2:02

within this method we're provided the

2:04

value for the column and we can actually

2:05

take that value and convert it using any

2:07

Lux and date time method that we might

2:09

want to choose in this case they're

2:10

using two format to change the format

2:12

value as they were showing in the

2:13

previous example so here's a look at the

2:15

two side by side the model one will run

2:17

every single time that we query using

2:19

our model this top one will need to

2:21

execute any time that we query our users

2:22

on our own so that's one awesome level

2:24

of abstraction that lucid provides for

2:26

us that we don't need to worry about we

2:28

set it once and then we can forget about

2:29

it now whenever it comes time to

2:30

actually creating our models the acli

2:32

comes in very handy you can see here we

2:34

can use the make model command to easily

2:36

create a model by just providing in the

2:38

name so in this case user and that will

2:39

create the model for us within app

2:40

models and it will call it user.ts as

2:42

with everything else in Adonis there is

2:44

naming normalization going on here since

2:46

models generally represent a single

2:47

record for a table they're going to be

2:49

singularized so if you were to provide

2:51

users as the name adonisjs Will

2:53

normalize that to user automatically for

2:55

you but in addition to just creating the

2:56

model you can also pass in additional

2:58

Flags to create other things for the

3:00

model automatically so you can see here

3:02

we can provide in hyphen M to create a

3:04

migration automatically at the same time

3:05

we're creating the model there's a

3:07

hyphen f to do the exact same for a

3:08

factory factories are used so that we

3:10

can easily create loads of test data for

3:12

the model out of the get-go that's

3:14

provided an instance of Faker within

3:15

there so you can fill those up with a

3:17

bunch of fake data there's also a hyphen

3:19

C which isn't in this documentation set

3:20

here but that will create a controller

3:22

for the model as well and you can mix

3:24

and match those in any set that you

3:25

might need so you can do hyphen MC to

3:27

create a migration and a controller you

3:28

could do hyphen MF to create a migration

3:30

in a factory you can do hyphen MFC to

3:33

create a migration Factory and

3:34

controller all at the same time in

3:35

addition to the things that we've just

3:36

talked about models can also do loads of

3:38

other things for us including allowing

3:40

us to Define query Scopes allowing us to

3:42

extend our own methods off of it so that

3:44

we can easily reach for stuff that can

3:45

be both class and instance level methods

3:47

so we can either perform it in a broad

3:48

sense by doing it as a class method or

3:50

we can perform it on instance method to

3:52

do it for a single record within our

3:53

database and then as we saw a moment ago

3:55

with the serialize method here you

3:57

there's also other methods that you can

3:59

do off of this there is consumed so that

4:00

you can change how it's actually

4:01

consumed straight out of the database

4:03

there's prepare so you can change how it

4:04

goes into the database then there are

4:06

hooks that'll actually allow you to

4:07

chain in particular events that are

4:09

happening on a Model Ruby Scoops which

4:11

come in handy with the query Builder

4:12

which allow you to just pack a level of

4:14

different query statements into one

4:16

specific method there's the query

4:17

Builder as a whole which is the same as

4:19

the database query Builder but there's

4:21

also a lot of other methods available on

4:22

the model query Builder that aren't

4:24

available on the database query Builder

4:25

like preloading relationships that allow

4:27

us to take our querying just a step

4:29

further so that we don't need to

4:30

actually join everything anytime that we

4:32

want a relationship and in order to do

4:33

that we also need to Define our

4:35

relationships on the model as well which

4:37

just provides a universe of different

4:39

functionalities for us so we're going to

4:41

be spending the next several lessons

4:42

focusing specifically on models and all

4:44

of these things that we've just talked

4:45

about taking a look at them one by one

4:46

and we're also going to step through the

4:48

different crud actions as well but we've

4:49

spent a lot of time here looking at the

4:51

documentation what we need to do now is

4:52

actually create our models within our

4:54

project so if we jump back into our

4:55

project here we have our two migrations

4:57

our roles and users migrations now at

4:59

this time there's no automated process

5:01

to take this migration definition and

5:02

just convert it into a model it's a

5:04

manual process at present but it's

5:06

actually relatively easy if we utilize

5:08

some Visual Studio code options at our

5:10

disposal and one really cool thing to

5:12

have installed within Visual Studio code

5:13

is the adonisjs extensions pack this

5:16

provides you not only a number of

5:18

different things off to the toolbar that

5:19

I have hidden off on the left hand side

5:21

here or you might have it off to the

5:22

right hand side like being able to

5:24

visualize your routes and a number of

5:26

other things but if we hold command or

5:28

control shift p you'll see that we also

5:30

have all the ace commands available at

5:31

our disposal here one of which is this

5:33

make model so we can go ahead and click

5:35

on that provide in the model name so

5:37

let's do roll first so we can provide

5:39

enroll hit enter there then it'll step

5:40

through those flag options for us so it

5:42

will ask us first if we want to generate

5:43

out a migration for this model we

5:45

already have one here so I'm going to

5:46

hit no then it will ask us about a

5:48

controller we don't need one for roles

5:50

so we'll hit no on that as well and

5:51

it'll ask us about a factory we've

5:53

already generated out our rules within

5:54

that migration file using this defer so

5:57

we can go ahead and hit no on that as

5:58

well now convert if you don't want to

6:00

use that you can also jump into your

6:01

terminal go into your project and write

6:03

out the command manually so you can do

6:04

note Ace make model and call that roll

6:07

if you execute that it'll skip over it

6:09

since I've just created it but if you

6:10

don't have it created then it will go

6:11

ahead and make it for you so you'll see

6:12

a couple of things here first we have

6:14

that column decorator that we saw

6:15

previously on the documentation this

6:17

represents that the ID created at and

6:19

updated at are valid columns within our

6:21

database which if we were to take a look

6:22

right here jump into our roles you can

6:24

see we do indeed have an ID created at

6:26

an updated app but we also have a name

6:28

and description that we need to add in

6:29

here as well so what we can do is Define

6:32

these as columns so we can add in that

6:34

column decorator to find it as a public

6:35

property Define the actual column name

6:37

and then Define its type within a

6:39

typescript save type so it's not going

6:40

to be one to one with the actual type

6:42

that's in the database but it's going to

6:43

be close and it's going to be a

6:44

typescript representation that you use

6:45

so as you can see our ID is going to be

6:47

an integer within the database but

6:49

within our model it's a number and then

6:50

in addition to name we also have an at

6:52

column public for our description this

6:55

too is a string and there we go we have

6:57

our first model up and running and ready

6:58

to go already now there's a few things

7:00

that we haven't discussed here yet that

7:01

are going on within this particular

7:03

model so first within column we're

7:04

providing in an is primary true as an

7:07

argument to The Decorator as you might

7:09

have guessed this does actually

7:10

represent that this is a primary key

7:12

within the actual database so whether

7:14

you're using an ID a uuid you would want

7:16

that to be marked as is primary within

7:18

your model to represent that that is

7:20

your primary key then down here just

7:22

like it within the documentation example

7:23

we saw we're chaining off of our column

7:25

here an additional method called date

7:26

time as we previously discussed this

7:28

will actually take the date time out of

7:29

the database and then convert it into a

7:31

luxem date time within our model so if

7:33

we were to query our role using our

7:35

model then we would actually have the

7:36

Lux and date time value available to us

7:38

so with the date time method here we're

7:40

providing an auto create true and then

7:41

for updated out we're providing

7:42

additional auto update Trio there as

7:45

well so what this will do is whenever we

7:47

actually create a record using our model

7:48

it will auto create this created at an

7:51

update to have value based off of the

7:52

current time auto update will do the

7:54

same thing but for updating a record so

7:56

if you change a record's value so if you

7:58

change the name up data that will

8:00

automatically update to the current date

8:01

and time now there's loads of different

8:03

options for these particular arguments

8:05

and everything so the best place to find

8:06

that is within the documentation if you

8:08

go underneath preferences here for

8:09

database down here in the orm section

8:11

there is a decorator section here so you

8:13

can see all of the different decorators

8:14

a lot of these listed are going to be

8:15

for relationships which we'll get into

8:17

at a later point in time but you'll also

8:18

see you have this column one here along

8:20

with the column date and date time and

8:21

this is where you can find all of the

8:22

arguments that's the column and date and

8:24

date time decorators except so you can

8:26

see right down here in the option set we

8:28

have that column name serializes is

8:30

primary serialized prepare consume meta

8:32

and that looks to be the end of it of

8:34

this list the most important one the

8:35

note I think is the column name so if we

8:37

take a look at our actual database

8:38

you'll notice that the created that and

8:40

updated ad are snake case meaning that

8:42

they have underscores separating the two

8:44

different words that they would be if

8:46

they were in English if we take a look

8:47

at the model that was generated for us

8:49

they're in camel case so we have created

8:51

out with a capital A and then we have

8:53

updated that with capital A that's the

8:54

default naming convention with Adonis so

8:56

it expects a snake case in the database

8:58

and then camel case within your models

9:00

and this is just a developer experience

9:02

thing so that you don't have to use

9:04

snake case everywhere within your code

9:05

base you can use camel case which is a

9:07

more normalized developer naming

9:08

structure there but say you didn't want

9:10

to use that within your model say for

9:12

whatever reason you wanted to use snake

9:14

case or something else for a particular

9:15

column you can provide that in as the

9:18

column name and we could provide that in

9:19

as created at and then we can provide

9:22

whatever we wanted here for the actual

9:24

model representation so we could do this

9:27

is

9:28

created at again whatever you wanted to

9:32

essentially this column name is just

9:34

going to map whatever name we provide

9:35

here to the actual database column

9:37

created underscore at this is created at

9:40

doesn't make any sense so I'm going to

9:41

set that back to created at but do know

9:43

that column name there does exist if you

9:45

have any one Ops where you need to name

9:46

something abstract as its representation

9:49

from the database all right so that's

9:50

our role model next let's go ahead and

9:52

create our user model and for this one

9:53

let's go and use the terminal so that we

9:55

show both Fashions here so let's node

9:56

Ace make model user and let's also go

9:59

ahead and create a controller for this

10:00

so we can do hyphen C all right so it

10:02

looks like for some reason it failed to

10:04

finish out the command here but we do

10:07

indeed have our users controller and our

10:09

user model created successfully so I'm

10:11

going to go ahead and just ignore that

10:13

error for what it is and let's go ahead

10:15

and dive into our user model and you can

10:16

see we have the same thing that we

10:17

started out with with our role model so

10:19

we have an ID we've set the primary we

10:21

have created that and updated that set

10:22

the auto create and then updated app for

10:24

auto update now what we need to do is

10:26

convert all of our user columns into our

10:28

column in our models and what I like to

10:30

do for this is just to go ahead and copy

10:32

all of the different columns that you

10:33

need to actually convert into your model

10:34

columns go ahead and copy those jump

10:36

into your model go to where those need

10:38

to be added paste them in as the

10:40

migration statements that they are and

10:42

then we can use multi-line commands here

10:44

to alter this in one blow so holding

10:46

down option command or option control on

10:48

Windows hit the down arrow until you

10:50

have all of the different rows that you

10:52

just pasted and selected hold down shift

10:54

option and then you can hit the arrow

10:55

key right to highlight a whole set of

10:57

words so you can highlight table let go

10:59

of option right once more to get that

11:01

single dot character go ahead and cut

11:04

that out shift option Arrow right again

11:06

to copy the actual type for the column

11:08

now I'm going to cut this out so I'm

11:09

going to do command or control X and I'm

11:11

just going to go over highlighting two

11:12

more characters delete those out

11:14

highlight the word set and now I have a

11:17

convert to camelcase command installed

11:19

on Visual Studio code so I can do

11:20

command or control shift p and type in

11:22

camel case and then I can select this

11:24

change camel case so now those are

11:26

automatically changed the camel case for

11:28

me I'm going to hit right on Arrow key

11:29

to go beyond those column names and then

11:31

what I do at this point is note which

11:32

columns are nullable so it looks like

11:34

they're all not nullable we do want to

11:36

change our role to be not nullable but

11:37

we'll go ahead and hold down command or

11:39

control shift and then hit right on the

11:40

Arrow key to highlight the remainder of

11:42

that string and then we can hit delete

11:44

on that to get rid of it command and

11:46

then hit left to jump back to the start

11:48

of all of our strings type at

11:51

column and that hit enter type public

11:54

Command right to go to the end of the

11:57

word type colon and then paste in those

11:59

types that we copied earlier and then

12:00

hit enter to put a line break in between

12:02

all of those now we can jump down to the

12:04

end here get rid of that spare line

12:05

break and then all we need to do is go

12:07

through and convert the types from

12:09

database types to typescript types and

12:11

for our case here it's just this integer

12:13

needs to change the number and there we

12:15

have it there's our user and Role Models

12:17

setup configured and ready for us to

12:19

continue onward hopefully you enjoyed

12:20

this lesson if you did please consider

12:21

hitting the like button down below and

12:23

subscribing future lessons just like

12:24

this one we're going to be continuing

12:25

that Series going into depth on our

12:28

models here so if you'd like to learn

12:29

more please stick around I'll see you

12:31

all in the next one

12:32

[Music]

Join The Discussion! (0 Comments)

Please sign in or sign up for free to join in on the dicussion.