Defining One to Many Relationships with Lucid Models
In this lesson, we'll learn how to define one-to-many and many-to-one relationships using Lucid Models. We'll also learn how we can specify the columns that should be used for a relationship, allowing us to use one model for multiple relationships.
- Author
- Tom Gobich
- Published
- Mar 22
- Duration
- 6m 56s
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 One to Many Relationships with Lucid Models
-
(upbeat music)
-
So the remainder of the relationships
-
work relatively similar to our one-to-one relationships.
-
The only difference is they have their own decorators
-
and options sets we can provide into them.
-
So let's go ahead and jump into our user model.
-
And on this model, we have a role ID.
-
As we learned in our one-to-one lesson,
-
anytime that the role ID or relationship ID
-
is on the model that we're working with,
-
we'll want this to be defined as a belongs to
-
because that relationship belongs to the model
-
that we're working with.
-
So let's scroll down to the bottom
-
and we already know how this one works.
-
So we'll do @belongsTo,
-
provide that a callback function
-
that returns back our role model.
-
Declare role as belongs to type of role, just like so.
-
So our user here can only have one role.
-
However, our roles can have many users bound to them.
-
So on our role side, this, instead of being a has one,
-
would instead wanna be a has many
-
because any one role can have many users.
-
We'll return this back our user model instance
-
inside of its callback,
-
and we will declare and call this users
-
has many type of user.
-
We're gonna get a red squiggly again
-
because that did not auto import
-
with the type declaration on it.
-
So we'll add that in and now everything's happy.
-
The options for our has many
-
are relatively similar to our has one.
-
We're gonna have a local key and a foreign key.
-
The local key is going to be the relationship key
-
for the model that we're currently on.
-
So that would be our roles ID.
-
So we could provide that in there if we wanted to.
-
And the foreign key would be the relationship ID
-
on the model that we're relating to.
-
So our user model, if we scroll down,
-
that would be our role ID.
-
So we could provide that in there if we wanted to.
-
Again, though, for these, we are using the defaults.
-
We already know that our local key is definitely ID,
-
so we can get rid of that.
-
And our foreign key will take our roles name
-
plus its primary key of ID.
-
So that would be role ID,
-
concatenate them together in a camel case fashion,
-
which would result in role ID as we have it here.
-
So we can get rid of that one there as well
-
and just use the defaults.
-
Cool, so that's how you define one to many
-
or many to one relationships,
-
depending on what side of the relationship
-
you're looking at it on.
-
If you're looking at that from our user side,
-
our user can have one role,
-
so that would be a many to one.
-
We have many users going to one particular role.
-
If we're looking at that from our role side,
-
we have one role pointing to many users.
-
So that would be a one to many,
-
many to one, one to many.
-
And we have that going on in a couple more places as well,
-
primarily on our movie,
-
where we have our status ID, writer ID and director ID.
-
Since our movie model contains the IDs
-
for all three of these relationships,
-
all three will be defined as a belongs to.
-
So we can scroll down to the end of our column declarations,
-
but before our query scopes and define them here.
-
So at belongs to, we'll start with our movie status.
-
So we'll do movie status,
-
whoops, not the enum, movie status, our model.
-
There we go, declare.
-
And you can either name this movie status
-
if you wanna be verbose,
-
or you could just name this status,
-
belongs to type of movie status.
-
Again, the actual name that you give the column
-
doesn't matter so much,
-
especially in terms of defaults for the relationship.
-
That's the model names and the primary keys that use those.
-
So we need to specify this as a type import yet again.
-
So let's scroll back up, add type there,
-
and scroll back down.
-
And for this one,
-
we do need to change the options a little bit
-
because we're not actually making use of the Lucid defaults.
-
So our model name is movie status
-
and its primary key is ID.
-
So what this would be expecting for our foreign key
-
by default would be movie status ID.
-
However, if we scroll up,
-
we'll see that we're actually calling this just status ID.
-
So we're not making use of the default
-
for this relationships naming convention.
-
And so we will need to specify that as just status ID here
-
so that Lucid knows the correct column to use
-
when matching this relationship together.
-
But with that set,
-
we are A-okay with our belongs to for our status.
-
We can give this a copy and a paste one time.
-
And now let's do our director ID.
-
So that uses our Cinest model
-
and the column name here will be our director.
-
And again, this will be our Cinest model.
-
Now, yet again,
-
we're going to need to define the foreign key
-
for this relationship
-
because AdonisJS's default will be expecting Cinest ID
-
as that's our model name.
-
And that model's primary key is ID.
-
However, we have this relationship called director ID.
-
So we're gonna wanna give that column there a copy,
-
jump back down to our relationship definition
-
and paste that in.
-
So now Lucid knows to use our director ID
-
anytime that we're trying to query our director
-
from our movie.
-
We can give this one here a copy
-
and a paste yet again for our writer.
-
Now our writer also uses the Cinest model,
-
but we'll want it to be called a writer for the column name.
-
And it's foreign key is not director ID,
-
but instead writer ID.
-
So as you can see, using the relationship arguments,
-
this is how we can go about using one model
-
for multiple different relationships,
-
depending on the particular foreign key that we provide,
-
in this case for the belongs to relationship.
-
Remember belongs to is the one
-
where this is a little bit backwards
-
and the foreign key is on the same model we're working with.
-
With all of the other ones,
-
foreign key is the related models ID for the relationship.
-
Cool, so we should have all three of these set
-
for this side of the relationship.
-
Let's jump over to our movie status
-
and take care of that side.
-
Again, any one movie status
-
can have many movies bound to it.
-
So this will be a has many here as well.
-
We'll return a callback that returns back our movie model
-
and declare movies as type has many type of movie.
-
And we need to fix that type import once more,
-
just like so.
-
And again, since we're working with has many now,
-
our movie status model, plus its primary key of ID
-
is not the correct default foreign key
-
that we would expect for this relationship.
-
So we need to provide in that foreign key
-
for this relationships definition,
-
and that will be our status ID column on our movie model.
-
Cool, so that one there should be good now as well.
-
Let's jump over to our Sinus model.
-
And we're gonna have a couple for this one.
-
So let's scroll down.
-
We'll do this underneath our computed column.
-
And we're gonna have both a writer and director ID
-
pointing to our movie.
-
And any one Sinus can either write or direct
-
multiple movies, so both will be a has many.
-
So add has many there,
-
provide a callback function pointing to our movie model.
-
Scroll down a little bit.
-
Let's declare.
-
For right now, let's just call this movie.
-
And then the type will be has many type of movie.
-
And let's go up and fix our type import real quick.
-
Okay, and let's give this a quick copy and a paste.
-
So we're gonna have one for our director
-
and one for our writer.
-
We already know that we need to provide the foreign key
-
to specify which is which here.
-
So foreign key, this one will use our director ID
-
on our movie model.
-
And this one will have a foreign key
-
pointing to our writer ID on our movie model.
-
And now we can specify whatever name we want
-
to appropriately assign that this relationship
-
is for our Sinus directed movies.
-
And this relationship is for our Sinus written movies.
-
So for that, we could do something like movies directed
-
and movies written.
-
But again, you can name these whatever you want
-
for the actual column names.
-
Okay, so it should be all set
-
with our relationship definitions on our models.
-
Now we need to add in fake data for both of these
-
so that we have something to work with.
-
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!