Listing and Counting a Writer's Movies
In this lesson, we'll learn how we can perform multiple different relationship counts with the same relationship using the Model Query Builder. We'll count our writer's total number of released and not-released movies.
- 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 and Counting a Writer's Movies
-
(upbeat music)
-
So let's go about that exact same flow,
-
but for our writers and with some new stuff tied in.
-
So let's go ahead and create a writer's controller
-
with an index and show method bound in.
-
So we'll stop our server, node, ace, make controller,
-
writers with an index and show method added in.
-
Go ahead and boot back up our server
-
and jump back into our text editor.
-
For the most part, our query for our index page
-
is going to remain the same.
-
We'll add in some additional stuff to it,
-
but it will be relatively similar
-
so we can start from it as a base point.
-
So let's do const writers equals
-
and let's paste in what we've copied.
-
Now we'll need to re-import our cinist.
-
So I'm just going to type out cin
-
and then hit tab to auto import that.
-
And instead of where has movies directed,
-
this will be where has movies written.
-
Then we can return and we need to extract out our view
-
from our HTTP context, view, render pages,
-
writers slash index.
-
We can provide in our writers there.
-
Let's get this working
-
before we add some additional stuff to it.
-
So let's jump back to our routes.
-
We can go ahead and copy both of these,
-
paste it in since we're going to have
-
just writer versions of both of these.
-
Hit option command down to get multiple cursors,
-
option shift right to select the whole word directors
-
and replace that with writers.
-
Okay, hit escape to go back to a single cursor,
-
jump over to our director's controller here.
-
Let's go into the middle of it,
-
option command down again to get multiple cursors,
-
option left arrow to jump to the start of the word,
-
option shift right arrow to jump to the end of the word
-
and select the entire word director's controller.
-
And let's type out writers controller
-
and hit tab to auto import that.
-
Lastly, command right arrow to jump to the end of the line,
-
option left arrow two times,
-
and then just left arrow once more
-
with option shift left arrow
-
to highlight our whole director's word,
-
replacing that with writers.
-
If you're not familiar with those keyboard shortcuts,
-
it's worth the time to go through that flow
-
over and over again so that you get them mentally mapped
-
because they really do save you quite a bit of time.
-
Okay, so we have our routes, let's create our pages next.
-
We can just right click and copy our director's directory,
-
right click on pages and paste that in.
-
It's gonna be called director's copy, that's okay.
-
Hit enter on that so that we can rename it to writers.
-
We open that back up, jump into our show page
-
because we have director explicitly written right there.
-
And let's switch that to writer, switch this to writer.
-
And we're gonna go about this a different approach,
-
so we will need to switch movies,
-
but we'll leave that as is for right now as well.
-
Our index page has something similar going on.
-
Directors, we'll switch to writers,
-
directors to writers yet again, director to writer,
-
writers, writer, and writer.
-
Okay, there was more on that page than I remembered,
-
we should just did a find and replace, but that's okay.
-
Lastly, let's jump into our navigation,
-
copy our director's href, paste that in,
-
switch that to writers and switch this to writers as well.
-
So now we should be able to open back up our browser
-
and we should have a writer's option up here
-
in our navigation that we can click.
-
And let's see if we had any differences here.
-
A couple, yep.
-
So it seems like Jane Dickey is a director,
-
but not a writer and Bernie Rogan is a writer,
-
but not a director.
-
We are working with a pretty small pool of people,
-
so there's not gonna be much of a change here,
-
but we do see some change, so we know that's working.
-
So let's jump back into our writer's controller.
-
And now let's say that we want to display
-
the number of movies that these writers have written.
-
After our where has, we can use a method called with count
-
to count the number of movies related to this user
-
where they have written the movies.
-
And for that, we can use our movies written relationship.
-
This will add a count onto the extras object of our writers.
-
Our model query builders will always return back
-
an instance of the model.
-
Any properties that don't exist on that model
-
explicitly included inside of our query,
-
like our movies written count will be,
-
will then be placed on the extras object.
-
And just like our where has here,
-
we can copy that and add that in as a second argument
-
to our count to restrict our movies written count
-
to just movies that have already released.
-
So if we dive into our writer's index page,
-
let's do a span class text slate 400.
-
And we'll display this count inside of parentheses
-
and we'll do double curly braces here
-
so that we can reach into writer dot
-
and we'll reach for our dollar sign extras object.
-
And there should be a concatenation
-
of the relationship name underscore count.
-
So that would be movies written underscore count.
-
All right, let's see if we got that right.
-
Let's jump back into our browser and look at that.
-
So we have Alvina Barrows wrote 45 movies
-
and we need Doyle 42, 42 there, 35, 34.
-
Awesome, so that seems to be working.
-
Let's hide our browser back away,
-
jump back into our writer's controller.
-
Now let's say we also wanted to do with count,
-
but where the movie is not yet released.
-
So movies coming soon or something like that.
-
Well, we can give this specific with count a name
-
by inside of the query callback,
-
chaining off of it and as,
-
and then providing the name in there.
-
So we could do something like released count there.
-
Let's give that a copy before we save, paste it in,
-
switch our query scope to not released for the second count
-
and switch the name to not released count.
-
Now we'll give that a save so that it formats,
-
jump back into our writer's index page.
-
And now we need to switch this reference
-
from movies written underscore count,
-
which is the automatic name that Lucid will provide to it,
-
to our manual name of released count.
-
And we can add in released comma,
-
and now we can do writer.extras.notreleasedcount
-
as we'll just say not released there.
-
Let's jump back into our browser
-
and our released looks the same,
-
but we do get back zero across the board for not released.
-
So if we dive back into our text editor here,
-
go down into our database and our fake cedar.
-
Right here we have two movies being created
-
with written soon and they should have
-
one specific writer attached to it.
-
So we should have at least two people
-
with a not released movie.
-
Let's take a look here.
-
So right here, we are limiting our writers
-
to just those that have a released movie.
-
And within our fake cedar,
-
we're creating two specific writers
-
for these not released movies.
-
So we do wanna get rid of this release specification here
-
because that limits our writers to just those
-
that have written a movie and that movie has released.
-
So if we get rid of our query scope there
-
to include those that have not yet released,
-
give that a save, jump back into our browser,
-
give this a refresh.
-
There we go.
-
And now we have one, two, three, and four writers
-
who don't have a released movie,
-
but do have a not released movie.
-
So let's jump back into our fake cedar
-
to make sure that that is right.
-
So we know that we have two here.
-
Ah, yeah, post-production is also not released.
-
So that would be four.
-
Okay, cool.
-
So that looks right there.
-
So let's jump back into our writer's controller
-
and let's go ahead and fill out the show method.
-
So again, for this one, we're gonna want view and params.
-
And now we can get const writer equals await cinist.
-
And this time we're gonna use the cinist query builder
-
to find our writer.
-
So we can do .where that writer's ID is our params ID.
-
If you wanted to, you could also provide this as an object.
-
So ID as the column and params.id as the value,
-
that will work as well,
-
which will limit our cinist down to just the one cinist
-
that we're looking for.
-
And then we can do first or fail.
-
And now we have a query relatively similar to,
-
if we scroll up and go to our director's controller,
-
this line right here.
-
So both of these lines get us the same result.
-
However, we can use eager loading,
-
so preload to attach the movies that this writer has written.
-
And since on our index page,
-
we're including those movies
-
where they are not quite released,
-
we'll leave this as is.
-
But if we wanted to limit this preload
-
to just movies that were released,
-
we could do query, query.apply, scope, scope.released,
-
like so to get that result.
-
But we'll include those here.
-
Okay, let's go ahead and return,
-
view, render, pages, writers, show,
-
and provide in our writer.
-
So now we have all of the information
-
on one variable of just writer,
-
whereas on our director's controller,
-
we had it as director and movies.
-
So within our writer's show page,
-
we're gonna need to reflect that.
-
So instead of just movies here,
-
this is going to be writer.moviesWritten.
-
And then we can loop over each of the movies
-
that they've written and apply their card.
-
Okay, so now we should be able to dive
-
back into our browser.
-
I can't quite recall who we were working with
-
on our writer two lessons ago,
-
so we'll just click on somebody random here.
-
And there we go, we see a number of different movies
-
that this person has written.
-
If we go back, let's click on somebody who only has one.
-
So Bernie Rogan right here, just wrote "Grease," okay.
-
So let's click on somebody
-
who doesn't have a released movie yet.
-
So Johnny here, "Sugar Shack," okay.
-
So all of that is looking a-okay.
-
[ illegible ]
-
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
-
7.0The Flow of Middleware7m 49s
-
7.1Authenticating A Newly Registered User4m 14s
-
7.2Checking For and Populating an Authenticated User2m 10s
-
7.3Logging Out An Authenticated User2m 24s
-
7.4Logging In An Existing User6m 54s
-
7.5Remembering A User's Authenticated Session6m 55s
-
7.6Protecting Routes with Auth, Guest, and Admin Middleware5m 36s
-
-
Filtering and Paginating Queries
-
8.0Creating A Movie List Page3m 43s
-
8.1Filtering A Query By Pattern Likeness7m 9s
-
8.2Filtering Our List by Movie Status5m 47s
-
8.3How To Apply A Dynamic Sort Filter To Your Query7m 12s
-
8.4Joining SQL Tables To Order By A Related Column4m 49s
-
Validating Query String Filter Values7m 23s
-
How To Paginate Filtered Query Results9m 15s
-
Pagination First, Last, Next, and Previous Buttons4m 2s
-
-
User Watchlist
-
An Alternative Approach to Many-To-Many Relationships4m 56s
-
Toggling A Movie in an Authenticated User's Watchlist9m 56s
-
Listing and Filtering User Watchlist Items7m 34s
-
Allowing Users To Toggle A Movie As Watched4m 44s
-
Filtering By User's Watched Status6m 7s
-
Defining A Composite Unique Constraint4m 46s
-
Join The Discussion! (0 Comments)
Please sign in or sign up for free to join in on the dicussion.
Be the first to Comment!