Defining A Structure for our Movie using Models
In this lesson, we'll introduce the concept of models by using one to define the properties our movies should contain. We'll then stub some methods that will mock calls we'll later be able to use to load data from our database.
- Author
- Tom Gobich
- Published
- Jan 31
- Duration
- 9m 38s
Developer, dog lover, and burrito eater. Currently teaching AdonisJS, a fully featured NodeJS framework, and running Adocasts where I post new lessons weekly. Professionally, I work with JavaScript, .Net C#, and SQL Server.
Adocasts
Burlington, KY
Transcript
Defining A Structure for our Movie using Models
-
[MUSIC]
-
So currently we're building out our movies in two different ways.
-
Within our index method, it's all one object,
-
and then within our show method,
-
it's two different objects.
-
So here in our index method,
-
we're pushing into a movie's array,
-
one single object that represents an individual movie,
-
and then down here within our show method,
-
we have the MD which contains one set of data for a particular movie,
-
and then we have the movie HTML that represents the actual content.
-
Ideally here for a movie resource,
-
we would have one concise structure that we would adhere to
-
throughout our application on what a movie is and contains.
-
That's where models come into play.
-
Whenever we created our project,
-
a user model was created for us.
-
There's a lot that's going on here,
-
but primarily all that you need to worry about right now is that it's a form of
-
a class and it declares
-
particular properties that we expect the underlying class to have.
-
So here we have a user model,
-
and we're defining that the user has an ID,
-
a full name, email, password,
-
a created at, and updated at property within it.
-
The extra decorators that you see on here like column and
-
column.dateTime are used by Lucid which is AdonisJS's ORM to determine
-
whether or not the property within the model
-
is an actual column representation from the database.
-
So primarily long-term speaking,
-
models are a way for us to describe
-
our tables that we have in our database within our code.
-
Today though, we can go ahead and get started with models by using it as a way to
-
define one concise structure for what a movie should
-
be and the different types of data that it should hold.
-
So let's go ahead and dive into our terminal.
-
Let's stop our server, clear it out,
-
and let's run node, ace, list.
-
Within our make commands,
-
we see a command specifically for making a model.
-
So let's go ahead and use that to create a movie model.
-
So we'll do node, ace, make, model, movie.
-
Go ahead and run that, and there we go.
-
Now we have an app models movie file that we can reference within our code base.
-
So let's go and open our code back up and take a look at our new model.
-
So currently we have our movie class and it's extending a base model.
-
This base model is going to bring in Lucid.
-
We're not quite there yet,
-
so let's go ahead and get rid of that for right now.
-
We'll also go ahead and get rid of the column decorators,
-
as we're not quite ready for that yet either.
-
We can get rid of the import,
-
and we can actually get rid of all of the properties that we have within here so far.
-
Cool. So we're really just down to a class at this point.
-
If we take a look at one of the movies that we have defined,
-
we have a title and a summary within our front matter data,
-
and then we have this lipsome text that serves as an abstract about the movie.
-
So we can add declarations to our movie model for these properties,
-
so that we have one concise definition on what a movie is.
-
So let's go ahead and declare that the movie is going to have a title of type string.
-
We will declare that it will have a summary of type string,
-
and we'll declare that it has an abstract of type string.
-
Now, we're missing one declaration and that's our slug,
-
which is what we use to uniquely identify what a movie is in a human readable format,
-
i.e. our file name for the actual movie.
-
So underneath our title,
-
let's declare slug and that too is of type string.
-
Cool. So now we have all of the different properties that we're going to need to
-
specify what exactly a movie is at the present point in time.
-
Let's go ahead and make use of it.
-
So let's jump into our movies controller and let's start with our index method.
-
So instead of pushing just any old object into our movies array,
-
that's of type record any,
-
let's switch this to be of type movie,
-
and we'll import our new movie model,
-
still leaving the array at the end so that it's now an array of movie models.
-
Now, although the object that we're passing into our movies array
-
matches pretty closely to our movie model,
-
it's not a one-for-one match with what we have defined in the model itself,
-
because currently we have the abstract as required.
-
If we wanted to, we could say that this is optional,
-
give that a save, and now jump back into our movies controller,
-
and this would turn into a happy object.
-
But let's take this one step further and actually make this object an instance of our movie.
-
So let's do const movie equals new movie.
-
On the movie itself,
-
we'll set the title and we'll set that to empty front manner title,
-
just as we have it in our object.
-
And let's do the same for our summary and slug.
-
So movie.summary equals empty front manner summary.
-
Movie.slug equals, and then this we have accessible just via slug.
-
Now, instead of pushing just this object,
-
we can push our movie into our movies array.
-
So this already matches what we had previously,
-
we're just now making it a specific instance of our movie.
-
So everything on our homepage should still work A-OK.
-
So let's go ahead and open it up, give it a refresh.
-
Oh, we need to restart our server.
-
So let's jump back into our terminal here,
-
npm run dev to boot that up.
-
Cool. Now, let's give the page a refresh again.
-
And yep, everything's still working A-OK.
-
We can hide our browser back away and let's move on to the show page.
-
We have a little bit of work here to do for our show page because we're using
-
two different properties to show two different things within the page itself.
-
Underneath our MD, let's go ahead and create a new instance of our movie.
-
So we'll do movie equals new movie.
-
Instead of setting the HTML contents directly onto a variable called movie,
-
we can instead set this directly on movie.abstract.
-
In addition to that, we can do movie.title equals MD front matter.title.
-
And let's actually just scroll up and copy what we have from our index page here.
-
Paste this down here.
-
And then our slug can come from params.slug.
-
Now, we no longer need to pass MD into our page because we have all of
-
the information that we need directly on our movie instance.
-
So let's go and get rid of that, give this a save.
-
Now, we need to jump into our page, scroll down a little bit.
-
And here, we're referencing our front matter title.
-
Let's just switch this to movie.title.
-
And here, we're referencing just movie, where we previously had our HTML stored.
-
Instead, this is now movie.abstract.
-
So now we should be able to give this a save, jump back into our browser,
-
try viewing one of our movies.
-
And cool, still works the same as before.
-
We can hide our browser back away.
-
But now our controller is kind of back to how we were before,
-
where we now have the same code defined in two different places inside of our show
-
and index pages.
-
We could move this out to a service.
-
But whenever we get to the point where we actually attach our movie model
-
to the database, we're going to have some abilities within the model itself
-
to query information from our database via some methods.
-
So instead of moving the reusable code out of our controllers and into a service,
-
let's mimic those methods within our movie model.
-
So in our movie model, we'll have a static async method called find.
-
And this will accept in an ID.
-
Now, currently, we don't have an ID.
-
But we do have a slug.
-
And our slug kind of serves the same purpose as an ID would
-
whenever we get to databases.
-
Our slug's unique.
-
And it represents one particular movie within the movies that we have.
-
So for now, let's use our slug for our find method.
-
So first, we're going to want to try and fetch a movie for the slug.
-
And we can do that using our movie service.
-
So we'll do const md equals await movie service.
-
Hit Tab to auto-import that.
-
Read.
-
And we can pass the slug in.
-
Next, let's go ahead and create a new instance of our movie
-
by doing const movie equals new movie.
-
And let's populate the properties that we have.
-
I could retype all this.
-
Or we could jump back into our movies controller,
-
go on down to our show method, where we have all of this already taking place.
-
We'll give this a copy.
-
Jump back into our movie model, paste it in.
-
It's no longer param slug, but just slug.
-
And we need to import to HTML.
-
So let's jump back into our movies controller, scroll up to the top,
-
copy this import, and let's paste it into our movie model, just like so.
-
Scroll back down, and we're good to go there.
-
Lastly, we just want to return back the new movie that we've created.
-
So movie.
-
So we can give this a save, jump back into our movies controller,
-
go back down to our show method.
-
And look at that.
-
We've just replicated this whole portion right here.
-
So now we can do const movie equals movie.find params.slug
-
to provide it in the slug.
-
And now we're down to just two lines for our show method
-
inside of our controller.
-
Let's give this a save.
-
And now let's do the same thing for what we have going on
-
within our index method.
-
Jump back into our movie model, scroll up just slightly,
-
and let's put this above our find method.
-
We'll add in another static async method here.
-
And let's call this all.
-
This method's going to be in charge of returning back
-
all of the movies that we have.
-
So first things first, we're going to want these slugs that we created.
-
We can get from our movie service.
-
So we'll await movie service.
-
And let's get slugs.
-
Then let's do const movies equals an empty array.
-
If you want to, you can specify that this
-
is going to be a movie array.
-
And then we'll loop over them.
-
So let's do for const slug of slugs const movie equals await.
-
And within our movies controller here,
-
this is where we're recreating the movie
-
and then pushing it into our movies array.
-
However, we now have a find method on the model itself
-
kind of doing this exact same thing.
-
So instead of redoing that code, we can instead call this.find,
-
pass in the slug, and now we have access to our movie thanks
-
to the find method actually finding it from the directory,
-
pushing it out, and populating the data.
-
Meaning all that we have to do within our all method
-
now is push this into our array.
-
So movies.push movie.
-
Lastly, we just need to return back the movies.
-
So return movies.
-
Let's give this a save.
-
Oh, got a typo up here.
-
This should be slugs, not slug.
-
There we go.
-
And now we can jump back into our movies controller.
-
Everything that we have here can now be removed.
-
And instead, we can do const movies
-
equals await movie.all.
-
And now we're down to just two lines for this method as well.
-
That really trimmed up our movies controller quite a bit.
-
Let's give that a save, and let's test everything out.
-
So we'll jump back into our browser.
-
Let's give this page a refresh for sanity's sake.
-
Well, uh-oh.
-
Now we have undefined undefined.
-
Let's see if things are working on our home page.
-
Yep, still looks good there.
-
So we need to figure out what's going on here.
-
So since our home page is working,
-
we know that data is populating OK,
-
because at the end of the day,
-
this is still calling the find method within our model.
-
So let's go ahead and retrace the steps
-
on what might be going wrong here.
-
So let's hide our browser back away.
Join The Discussion! (8 Comments)
Please sign in or sign up for free to join in on the dicussion.
amitava-mukherji
cannot fine module 'luxon' or its corresponding type declarations
Please sign in or sign up for free to reply
amitava-mukherji
error message: Argument of type 'Hash' is not assignable to parameter of type '() => Hash'.
Please sign in or sign up for free to reply
amitava-mukherji
Command "make:model" is not defined
Please sign in or sign up for free to reply
tomgobich
Hi Amitava! Can you please provide some additional context around these errors? Did you clone this series' repo at a certain branch? Is this a brand new AdonisJS 6 project?
Please sign in or sign up for free to reply
antoniogiroz
I've found the same error running "node ace make:model movie"
This command is unavailable in the ace make options (running "node ace list").
Please sign in or sign up for free to reply
tomgobich
Hi Antoniogiroz! Please make sure you have Lucid installed and configure inside of your project.
Then
If you continue to have issues, please provide some more details or a repository with a reproduction of your issue.
Please sign in or sign up for free to reply
antoniogiroz
It works! Thanks!
Please sign in or sign up for free to reply
tomgobich
Awesome to hear! Anytime!!
Please sign in or sign up for free to reply