🕑 Chapters:
- Database Query vs Model Query
- Model Creation Flags
- Model Features
- Creating Our First Model
- Column Decorator Arguments
- Default Column Naming Convention
- Converting Migrations To Models
- Outro
📜 Transcript:
with adonisjs there's two different ways
we can actually communicate with our
database so you have the database module
and then you have models now models
serve as the recommended interface to
actually communicate with your database
and then falling back to the database
module anytime that models can't fill
the void that you're looking for now
models follow the active record pattern
meaning that they're going to serve as
encapsulations for the database
interactions that we'll be doing and
they'll provide back objects or classes
that are type safe for us so a model is
going to serve as a representation of an
actual database table so for the most
part we're going to want one model per
table within our database with the
exception of those many to many pivot
tables in the long run by utilizing
these models we're actually going to
save ourselves a ton of code so if we
actually take a look here adonisjs has
an example on their documentation here
so here's an example of what a query
looks like without models so you query
it from the database using the database
module and then you represent what table
you want to pick from selecting The
Columns then you get back all of those
users then anytime that you query those
users for display you're going to need
to Loop over them to convert any
database values to display safe values
so in this example here they're looping
over the users getting a single user
within this call back here then they're
converting that user's date of birth
using luxem date time they're ingesting
that date of birth and then changing its
format with models this is vastly
simplified and we only need to perform
this conversion once and adonisjs will
recognize we want to do that every
single time so if we actually take a
look at their example here we have a
user model which is represented by a
class that extends a base model in this
column decorator represents the actual
property that is decorating is a valid
column within our database table off of
the column decorator we're chaining off
a date method the State method actually
instructs Lucid to actually take that
value convert it from that date or date
time string from the database and
convert it into a lux and date time
object for us automatically no
additional checks needed on our part now
within the State method we're actually
providing an option to serialize the
serialize method will run anytime that
our user model is actually serialized so
really anytime that we're passing it
from Adonis to outside the Adonis
ecosystem this could be returning it as
an API response or it could be returning
it from Edge to our front end code base
and down here they do have an example of
how to actually go about serializing
this manually as well but this method
will run anytime that that happens and
within this method we're provided the
value for the column and we can actually
take that value and convert it using any
Lux and date time method that we might
want to choose in this case they're
using two format to change the format
value as they were showing in the
previous example so here's a look at the
two side by side the model one will run
every single time that we query using
our model this top one will need to
execute any time that we query our users
on our own so that's one awesome level
of abstraction that lucid provides for
us that we don't need to worry about we
set it once and then we can forget about
it now whenever it comes time to
actually creating our models the acli
comes in very handy you can see here we
can use the make model command to easily
create a model by just providing in the
name so in this case user and that will
create the model for us within app
models and it will call it user.ts as
with everything else in Adonis there is
naming normalization going on here since
models generally represent a single
record for a table they're going to be
singularized so if you were to provide
users as the name adonisjs Will
normalize that to user automatically for
you but in addition to just creating the
model you can also pass in additional
Flags to create other things for the
model automatically so you can see here
we can provide in hyphen M to create a
migration automatically at the same time
we're creating the model there's a
hyphen f to do the exact same for a
factory factories are used so that we
can easily create loads of test data for
the model out of the get-go that's
provided an instance of Faker within
there so you can fill those up with a
bunch of fake data there's also a hyphen
C which isn't in this documentation set
here but that will create a controller
for the model as well and you can mix
and match those in any set that you
might need so you can do hyphen MC to
create a migration and a controller you
could do hyphen MF to create a migration
in a factory you can do hyphen MFC to
create a migration Factory and
controller all at the same time in
addition to the things that we've just
talked about models can also do loads of
other things for us including allowing
us to Define query Scopes allowing us to
extend our own methods off of it so that
we can easily reach for stuff that can
be both class and instance level methods
so we can either perform it in a broad
sense by doing it as a class method or
we can perform it on instance method to
do it for a single record within our
database and then as we saw a moment ago
with the serialize method here you
there's also other methods that you can
do off of this there is consumed so that
you can change how it's actually
consumed straight out of the database
there's prepare so you can change how it
goes into the database then there are
hooks that'll actually allow you to
chain in particular events that are
happening on a Model Ruby Scoops which
come in handy with the query Builder
which allow you to just pack a level of
different query statements into one
specific method there's the query
Builder as a whole which is the same as
the database query Builder but there's
also a lot of other methods available on
the model query Builder that aren't
available on the database query Builder
like preloading relationships that allow
us to take our querying just a step
further so that we don't need to
actually join everything anytime that we
want a relationship and in order to do
that we also need to Define our
relationships on the model as well which
just provides a universe of different
functionalities for us so we're going to
be spending the next several lessons
focusing specifically on models and all
of these things that we've just talked
about taking a look at them one by one
and we're also going to step through the
different crud actions as well but we've
spent a lot of time here looking at the
documentation what we need to do now is
actually create our models within our
project so if we jump back into our
project here we have our two migrations
our roles and users migrations now at
this time there's no automated process
to take this migration definition and
just convert it into a model it's a
manual process at present but it's
actually relatively easy if we utilize
some Visual Studio code options at our
disposal and one really cool thing to
have installed within Visual Studio code
is the adonisjs extensions pack this
provides you not only a number of
different things off to the toolbar that
I have hidden off on the left hand side
here or you might have it off to the
right hand side like being able to
visualize your routes and a number of
other things but if we hold command or
control shift p you'll see that we also
have all the ace commands available at
our disposal here one of which is this
make model so we can go ahead and click
on that provide in the model name so
let's do roll first so we can provide
enroll hit enter there then it'll step
through those flag options for us so it
will ask us first if we want to generate
out a migration for this model we
already have one here so I'm going to
hit no then it will ask us about a
controller we don't need one for roles
so we'll hit no on that as well and
it'll ask us about a factory we've
already generated out our rules within
that migration file using this defer so
we can go ahead and hit no on that as
well now convert if you don't want to
use that you can also jump into your
terminal go into your project and write
out the command manually so you can do
note Ace make model and call that roll
if you execute that it'll skip over it
since I've just created it but if you
don't have it created then it will go
ahead and make it for you so you'll see
a couple of things here first we have
that column decorator that we saw
previously on the documentation this
represents that the ID created at and
updated at are valid columns within our
database which if we were to take a look
right here jump into our roles you can
see we do indeed have an ID created at
an updated app but we also have a name
and description that we need to add in
here as well so what we can do is Define
these as columns so we can add in that
column decorator to find it as a public
property Define the actual column name
and then Define its type within a
typescript save type so it's not going
to be one to one with the actual type
that's in the database but it's going to
be close and it's going to be a
typescript representation that you use
so as you can see our ID is going to be
an integer within the database but
within our model it's a number and then
in addition to name we also have an at
column public for our description this
too is a string and there we go we have
our first model up and running and ready
to go already now there's a few things
that we haven't discussed here yet that
are going on within this particular
model so first within column we're
providing in an is primary true as an
argument to The Decorator as you might
have guessed this does actually
represent that this is a primary key
within the actual database so whether
you're using an ID a uuid you would want
that to be marked as is primary within
your model to represent that that is
your primary key then down here just
like it within the documentation example
we saw we're chaining off of our column
here an additional method called date
time as we previously discussed this
will actually take the date time out of
the database and then convert it into a
luxem date time within our model so if
we were to query our role using our
model then we would actually have the
Lux and date time value available to us
so with the date time method here we're
providing an auto create true and then
for updated out we're providing
additional auto update Trio there as
well so what this will do is whenever we
actually create a record using our model
it will auto create this created at an
update to have value based off of the
current time auto update will do the
same thing but for updating a record so
if you change a record's value so if you
change the name up data that will
automatically update to the current date
and time now there's loads of different
options for these particular arguments
and everything so the best place to find
that is within the documentation if you
go underneath preferences here for
database down here in the orm section
there is a decorator section here so you
can see all of the different decorators
a lot of these listed are going to be
for relationships which we'll get into
at a later point in time but you'll also
see you have this column one here along
with the column date and date time and
this is where you can find all of the
arguments that's the column and date and
date time decorators except so you can
see right down here in the option set we
have that column name serializes is
primary serialized prepare consume meta
and that looks to be the end of it of
this list the most important one the
note I think is the column name so if we
take a look at our actual database
you'll notice that the created that and
updated ad are snake case meaning that
they have underscores separating the two
different words that they would be if
they were in English if we take a look
at the model that was generated for us
they're in camel case so we have created
out with a capital A and then we have
updated that with capital A that's the
default naming convention with Adonis so
it expects a snake case in the database
and then camel case within your models
and this is just a developer experience
thing so that you don't have to use
snake case everywhere within your code
base you can use camel case which is a
more normalized developer naming
structure there but say you didn't want
to use that within your model say for
whatever reason you wanted to use snake
case or something else for a particular
column you can provide that in as the
column name and we could provide that in
as created at and then we can provide
whatever we wanted here for the actual
model representation so we could do this
is
created at again whatever you wanted to
essentially this column name is just
going to map whatever name we provide
here to the actual database column
created underscore at this is created at
doesn't make any sense so I'm going to
set that back to created at but do know
that column name there does exist if you
have any one Ops where you need to name
something abstract as its representation
from the database all right so that's
our role model next let's go ahead and
create our user model and for this one
let's go and use the terminal so that we
show both Fashions here so let's node
Ace make model user and let's also go
ahead and create a controller for this
so we can do hyphen C all right so it
looks like for some reason it failed to
finish out the command here but we do
indeed have our users controller and our
user model created successfully so I'm
going to go ahead and just ignore that
error for what it is and let's go ahead
and dive into our user model and you can
see we have the same thing that we
started out with with our role model so
we have an ID we've set the primary we
have created that and updated that set
the auto create and then updated app for
auto update now what we need to do is
convert all of our user columns into our
column in our models and what I like to
do for this is just to go ahead and copy
all of the different columns that you
need to actually convert into your model
columns go ahead and copy those jump
into your model go to where those need
to be added paste them in as the
migration statements that they are and
then we can use multi-line commands here
to alter this in one blow so holding
down option command or option control on
Windows hit the down arrow until you
have all of the different rows that you
just pasted and selected hold down shift
option and then you can hit the arrow
key right to highlight a whole set of
words so you can highlight table let go
of option right once more to get that
single dot character go ahead and cut
that out shift option Arrow right again
to copy the actual type for the column
now I'm going to cut this out so I'm
going to do command or control X and I'm
just going to go over highlighting two
more characters delete those out
highlight the word set and now I have a
convert to camelcase command installed
on Visual Studio code so I can do
command or control shift p and type in
camel case and then I can select this
change camel case so now those are
automatically changed the camel case for
me I'm going to hit right on Arrow key
to go beyond those column names and then
what I do at this point is note which
columns are nullable so it looks like
they're all not nullable we do want to
change our role to be not nullable but
we'll go ahead and hold down command or
control shift and then hit right on the
Arrow key to highlight the remainder of
that string and then we can hit delete
on that to get rid of it command and
then hit left to jump back to the start
of all of our strings type at
column and that hit enter type public
Command right to go to the end of the
word type colon and then paste in those
types that we copied earlier and then
hit enter to put a line break in between
all of those now we can jump down to the
end here get rid of that spare line
break and then all we need to do is go
through and convert the types from
database types to typescript types and
for our case here it's just this integer
needs to change the number and there we
have it there's our user and Role Models
setup configured and ready for us to
continue onward hopefully you enjoyed
this lesson if you did please consider
hitting the like button down below and
subscribing future lessons just like
this one we're going to be continuing
that Series going into depth on our
models here so if you'd like to learn
more please stick around I'll see you
all in the next one
[Music]
Join The Discussion! (6 Comments)
Please sign in or sign up for free to join in on the dicussion.
raymondcamden
I noticed this and the last tutorial are missing the transcript -is that a bug or just not yet written?
Please sign in or sign up for free to reply
tomgobich
T'was a bug. Should be all fixed up now, thank you, Raymond!
Please sign in or sign up for free to reply
raymondcamden
I can confirm - but I was also a bit confused. I was wondering why these 2 lessons don't have a "written" version like the earlier ones? I've been just reading, not watching the videos.
Please sign in or sign up for free to reply
tomgobich
Sorry about that! Since I manage this site and create the lessons in my spare time, cutting out the written portion and just focusing on video production was a decision made to help reduce the amount of time it took to create each lesson.
Please sign in or sign up for free to reply
raymondcamden
Understandable, and this is an incredible resource, so thank you for what you've shared here!
Please sign in or sign up for free to reply
tomgobich
Thank you, Raymond!!
Please sign in or sign up for free to reply