Listing A Director's Movies with Relationship Existence Queries
In this lesson, we'll learn how we can perform a relationship existence check to grab a list of our cineasts who have directed one or more movies. We'll then create a show page for that director, listing the movies that they directed.
- Author
- Tom Gobich
- Published
- Mar 26
- Duration
- 8m 41s
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
Listing A Director's Movies with Relationship Existence Queries
-
[MUSIC]
-
Now the fun begins.
-
Let's go ahead and create a page inside of our application that
-
lists all Cineasts who have directed any movies.
-
Then from there, we'll create a show page for that director,
-
listing all of the movies that they've directed.
-
Let's hit "Command P" and type in routes to jump into our routes file.
-
Underneath our movie show page,
-
let's go ahead and add in an additional page.
-
So router.get/, we'll call this directors.
-
Then if we stop and take a look at our controllers,
-
we don't have a controller applicable for this.
-
So let's dive into our terminal and let's run node,
-
ace, make, controller, directors.
-
Then we'll also want to stop it with a method called index.
-
So add index there to the end of this command. Let's run that.
-
There we go. So now we have a director's controller
-
with an index method stopped inside of it.
-
So we can type out director's controller,
-
hit tab to auto-import that just like so.
-
Once we save that, we'll switch to the correct lazy import here,
-
and we'll use the index method there since this will be
-
our listing page that will list all directors that we have.
-
So we'll call this as directors.index.
-
Once we save, we saw this switch from an orange tint
-
to a purple tint indicating that it did switch to a lazy import.
-
We'll hold option down to switch that to
-
down below our router import there
-
to keep all of our controller imports together.
-
Jump over to our director's controller,
-
and there is our stubbed index method.
-
Out of our HTTP context, let's grab our view,
-
and let's go and just start by returning view,
-
render pages/directors/show.
-
Let's create that page real quick.
-
Let's also go ahead and delete out the movies that we have
-
inside of our resources movies directory.
-
So we'll hit delete there, move that to the trash.
-
Let's go ahead and right-click that, new file,
-
add a folder called directors/,
-
and whoops, we're still on the index method,
-
so we'll want that to be called index, not show.
-
My bad there. So index.edge.
-
Let's jump back into our director's controller
-
and fix that real quick.
-
So instead of show, we do want this to be called index.
-
Okay, there we go.
-
So we'll do @layout, @ender layout,
-
and we'll just do an h1 of directors
-
so that we have something listing out this page.
-
Let's go ahead and dive into our partials
-
for our navigation,
-
and let's add in an additional anchor, href,
-
pointing to our route, directors.index,
-
and we'll call this directors.
-
Okay, give that a save.
-
We should now be able to jump into our terminal
-
and pm run dev to boot up our server.
-
Let's open up our browser.
-
Okay, here's our homepage.
-
If we click into directors now,
-
we get an h1 with directors.
-
Awesome. Let's hide that back away,
-
jump back into our text editor,
-
and let's go back to our director's controller.
-
We'll do const directors equals await.
-
We'll want to query from our Cynist model,
-
so we'll import that.
-
We're going to want to use the Cynist models query builder.
-
Now, we're going to want to query all Cineasts
-
who have a movie where they are the director ID.
-
So we're going to want to use,
-
if we dive into our Cynist model,
-
the movie's directed relationship
-
to check and see whether or not they have any records.
-
So for that, we could do where has
-
to check the existence of a relationship.
-
Whenever we hit the strings, we get IntelliSense popping up
-
that we have movies directed available to us.
-
If we needed to, we could provide a callback function
-
as the second argument here to extend
-
the movies directed query to add
-
additional statements to those movies.
-
For example, if the Cynist has
-
only directed movies that aren't out yet,
-
maybe we don't want to include them in this list.
-
So we could go ahead and apply a query scope
-
to our movies directed relationship from our movies query,
-
and this will be our movies query builder here.
-
So we have access to our scope.releasedQueryScope.
-
Now, if we hit "Save", the red squiggly is just due to formatting.
-
So there we go. Now, we should have directors who
-
have directed any movie that's already been released.
-
So we can provide that into our directors index as directors.
-
Let's dive back into that page.
-
For now, let's just do a ul,
-
each to loop over them,
-
director in directors at end are each,
-
and then we'll do an align here with our director full name.
-
Give that a save and let's go check it out to see if everything worked.
-
Jump back into our browser, and there we go.
-
Now, at this point, it's a little bit of a random list.
-
We don't have any sorting going on.
-
So let's fix that real quick.
-
Hide that back away, jump back into our directors controller,
-
and to the end of our query here,
-
we can add on a dot order by,
-
and we don't want to order by two columns,
-
the first name and then the last name.
-
We cannot order by a computed property
-
because it does not actually exist inside of the database.
-
So we can provide an array into this,
-
and in the first index,
-
we specify the column that we first want to order by,
-
which would be our first name.
-
The default direction is going to be ascending,
-
but if we need to change that or if we want to explicitly set it,
-
we can set it to order by ascending.
-
Then we can add in a second index here,
-
where the second column that we want to order by
-
is last name with the order of ascending there as well.
-
Give that a save. So we'll first order by our first name,
-
and then once it's done ordering by first name,
-
if we have any Sinus record using the same first name,
-
they'll then be ordered by the last name.
-
Cool. So let's jump back into our browser,
-
give that a refresh, and there we go.
-
So now they are listed in alphabetical order.
-
Now we need to be able to click into them and show
-
a details page with the movies that they have directed, listed out.
-
So I'll hide this back away.
-
So let's scroll down a little bit here,
-
and let's do a public show page.
-
We'll grab view out of that,
-
as well as our params,
-
HTTP context, and we'll go ahead and return view,
-
render pages, directors, show.
-
Before we go any further, let's define the route for this.
-
So we'll dive back into our routes.
-
Underneath our directors route,
-
we'll do router.get directors/,
-
and we don't have a slug for our directors,
-
and it's possible that directors could have the same first name and last name.
-
So for right now, we'll just need to do ID there,
-
and we can use the director's controller
-
and specify the show method there is directors show.
-
Let's round out our circle by diving back into our directors index page,
-
and let's add a link around our full name here.
-
So we'll do a href route directors show,
-
and let's add the param ID of director.ID.
-
We'll end our anchor and move that end tag down below our director full name.
-
Then we'll need to create our show page.
-
So I'm just going to copy everything that we have here
-
because it's going to be relatively similar,
-
and we can right-click our directors page,
-
new file, show.edge, paste that in.
-
Instead of directors up here,
-
this will instead be director.
-
Then we can list out their full name.
-
Then for our loop,
-
let's just jump back into our homepage,
-
and let's copy our div where we're using our cards,
-
jump back into our director show page,
-
highlight this, give that a paste,
-
and we can get rid of our URL.
-
Cool. Now, instead of coming soon,
-
this will just be all of their movies like so.
-
So we give that a save,
-
and let's jump into our movie card as well
-
because we're still using PIXM here,
-
but we have actual poster URLs tied to our movie now.
-
So we can replace that PIXM poster URL there as well.
-
Close that out because we're done with it.
-
Jump back into our director's controller,
-
and let's add in the query to get our director from our ID parameter
-
and their directed movies.
-
So const director equals await
-
cinist.findOrFailRams.id.
-
So we'll find or fail our cinist by their primary key ID column
-
provided into our route parameter ID value.
-
This also needs to be an async method.
-
There we go. So we can go ahead and add in our director
-
into our state for our page,
-
and now we need to get their movies.
-
So we can do await,
-
and for this, we can reach through this director
-
to get their related movies via its relationship.
-
So we can do director.related to reach through a relationship,
-
and we specifically want to use the movie's directed relationship here,
-
.query to get that relationship's query builder.
-
So now this is a movie query builder
-
using the relationship bound to this specific director.
-
So let's go ahead and order by that movie's title, okay?
-
And let's add the movies into our page state there as well.
-
We'll give that a save.
-
Let's jump into our browser and see if we got everything right.
-
So these are actual links.
-
They aren't shown like that because of the TailwindCSS reset,
-
but let's go ahead and click into Clark Strosen
-
because we were working with him in our last lesson.
-
So we know that he is bound to 310 to Yuma.
-
So we can click on him, and look at that.
-
His very first movie is 310 to Yuma.
-
And now we have all of Clark Strosen's directed movies listed out on his page.
-
Awesome. We'll add director to the start of the name
-
just so that we have that explicit.
-
So let's jump back into our show page here,
-
and let's do director, full name.
-
Okay, so now that should be director Clark Strosen.
-
There we go. Awesome.
-
So if we go back to our director's page, let's click on somebody else.
-
There's another handful of movies.
-
Click on somebody else, another handful of movies,
-
and let's click on somebody else.
-
And this person only has one,
-
so they are one of the ones that we created using the with method
-
with our movie factory.
-
So cool. Everything seems to work.
-
And even furthermore, we can click in to see the movie's details page
-
from each one of those.
-
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!