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.
-
And look at that.
-
So we have our await here,
-
but we forgot to await the find call.
-
So let's make sure that we await that there,
-
give that a save,
-
and hopefully that's all that we got wrong.
-
Let's open our browser back up here,
-
give the page a refresh, and there we go.
-
So now we see our movies details.
-
Go back to our home page.
-
Let's try another one, and let's try the third.
-
Awesome.
-
So that's all working A-OK,
-
And we've simplified our code base quite a bit in the process.
-
Introduction
-
Fundamentals
-
2.0Routes and How To Create Them5m 23s
-
2.1Rendering a View for a Route6m 29s
-
2.2Linking Between Routes7m 51s
-
2.3Loading A Movie Using Route Parameters9m 17s
-
2.4Validating Route Parameters6m 6s
-
2.5Vite and Our Assets6m 38s
-
2.6Setting Up Tailwind CSS9m 5s
-
2.7Reading and Supporting Markdown Content4m 32s
-
2.8Listing Movies from their Markdown Files8m 51s
-
2.9Extracting Reusable Code with Services7m 4s
-
2.10Cleaning Up Routes with Controllers4m 52s
-
2.11Defining A Structure for our Movie using Models9m 38s
-
2.12Singleton Services and the Idea of Caching6m 11s
-
2.13Environment Variables and their Validation4m 16s
-
2.14Improved Caching with Redis10m 44s
-
2.15Deleting Items and Flushing our Redis Cache6m 46s
-
2.16Quick Start Apps with Custom Starter Kits6m 28s
-
2.17Easy Imports with NodeJS Subpath Imports8m 40s
-
-
Building Views with EdgeJS
-
3.0EdgeJS Templating Basics8m 49s
-
3.1HTML Attribute and Class Utilities6m 9s
-
3.2Making A Reusable Movie Card Component10m 24s
-
3.3Component Tags, State, and Props4m 53s
-
3.4Use Slots To Make A Button Component6m 56s
-
3.5Extracting A Layout Component5m 13s
-
3.6State vs Share Data Flow2m 59s
-
3.7Share vs Global Data Flow6m 7s
-
3.8Form Basics and CSRF Protection6m 13s
-
3.9HTTP Method Spoofing HTML Forms3m 3s
-
3.10Easy SVG Icons with Edge Iconify7m 57s
-
-
Database and Lucid ORM Basics
-
4.0Configuring Lucid and our Database Connection4m 3s
-
4.1Understanding our Database Schema9m 35s
-
4.2Introducing and Defining Database Migrations18m 35s
-
4.3The Flow of Migrations8m 28s
-
4.4Introducing Lucid Models5m 43s
-
4.5Defining Our Models6m 49s
-
4.6The Basics of CRUD11m 56s
-
4.7Defining Required Data with Seeders11m 11s
-
4.8Stubbing Fake Data with Model Factories13m 48s
-
4.9Querying Our Movies with the Query Builder15m 30s
-
4.10Unmapped and Computed Model Properties3m 24s
-
4.11Altering Tables with Migrations7m 6s
-
4.12Adding A Profile Model, Migration, Factory, and Controller2m 57s
-
4.13SQL Parameters and Injection Protection9m 19s
-
4.14Reusable Query Statements with Model Query Scopes8m 11s
-
4.15Tapping into Model Factory States9m 15s
-
4.16Querying Recently Released and Coming Soon Movies4m 59s
-
4.17Generating A Unique Movie Slug With Model Hooks7m 59s
-
-
Lucid ORM Relationships
-
5.0Defining One to One Relationships Within Lucid Models5m 49s
-
5.1Model Factory Relationships2m 54s
-
5.2Querying Relationships and Eager Vs Lazy Loading5m 17s
-
5.3Cascading and Deleting Model Relationships5m 16s
-
5.4Defining One to Many Relationships with Lucid Models6m 56s
-
5.5Seeding Movies with One to Many Model Factory Relationships5m 24s
-
5.6Listing A Director's Movies with Relationship Existence Queries8m 41s
-
5.7Listing and Counting a Writer's Movies8m 41s
-
5.8Using Eager and Lazy Loading to Load A Movie's Writer and Director5m 18s
-
5.9Defining Many-To-Many Relationships and Pivot Columns9m 48s
-
5.10Many-To-Many Model Factory Relationships4m 50s
-
5.11A Deep Dive Into Relationship CRUD with Models18m 5s
-
5.12How To Create Factory Relationships from a Pool of Data13m 55s
-
5.13How To Query, Sort, and Filter by Pivot Table Data9m 47s
-
-
Working With Forms
-
6.0Accepting Form Data12m 15s
-
6.1Validating Form Data with VineJS9m 29s
-
6.2Displaying Validation Errors and Validating from our Request7m 16s
-
6.3Reusing Old Form Values After A Validation Error2m 3s
-
6.4Creating An EdgeJS Form Input Component5m 28s
-
6.5Creating A Login Form and Validator5m 1s
-
6.6How To Create A Custom VineJS Validation Rule9m 7s
-
-
Authentication & Middleware
-
The Flow of Middleware7m 49s
-
Authenticating A Newly Registered User4m 14s
-
Checking For and Populating an Authenticated User2m 10s
-
Logging Out An Authenticated User2m 24s
-
Logging In An Existing User6m 54s
-
Remembering A User's Authenticated Session6m 55s
-
Protecting Routes with Auth, Guest, and Admin Middleware5m 36s
-
-
Filtering and Paginating Queries
Join The Discussion! (0 Comments)
Please sign in or sign up for free to join in on the dicussion.
Be the first to Comment!