Introducing Lucid Models
In this lesson, we'll introduce models using the Lucid ORM. We'll learn how we can map database columns to our model properties and specify special behavior for our date time columns.
- Author
- Tom Gobich
- Published
- Feb 28
- Duration
- 5m 43s
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
Introducing Lucid Models
-
(upbeat music)
-
So at this point, we know that migrations are for defining
-
and altering the structure of the database,
-
defining the tables, the columns,
-
and the relationships using foreign keys.
-
So that's half the picture that we have taken care of.
-
Now we need the other half of the picture
-
where we actually define the structure of our database
-
to our application so that we can use it,
-
make queries against it, create data,
-
update and delete data as well.
-
And that's where models would come into play.
-
Models allow us to describe our database
-
and its structure to our application
-
so that we can create, read, update,
-
and delete data from our database itself.
-
We're gonna have one model per table
-
that we have inside of our database.
-
That one particular model will define all of the columns
-
and relationships specific to that one table.
-
Now, when we created our application,
-
AdonisJS started us off with a model for our user.
-
So far we've ignored it,
-
but if we scroll down a little bit,
-
we're gonna see that it's exporting a default class,
-
the same as we did with our movie model,
-
and it's calling a compose helper method.
-
Right now, all you need to know about this method
-
is that it's going to join two classes together
-
and allow us to extend off of both of them.
-
So essentially our user model is extending off
-
of a base model as well as an auth finder.
-
Auth finder is described right up here,
-
and this is what will come into play
-
whenever we talk about authentication.
-
For right now though, we're just going to ignore it
-
because it doesn't come into play
-
with anything that we're discussing
-
in this particular lesson or even module.
-
So at this point,
-
if we were to take authentication out of the question,
-
our model could look something like this.
-
It's just a user class extending a base model class.
-
This base model class is going to bring in
-
lucid superpowers, essentially allowing our class itself
-
to communicate with our database,
-
querying information, creating information,
-
updating and deleting as well.
-
It's also gonna use these column decorators
-
that we have added onto our property declarations
-
to describe these property declarations
-
as columns inside of our database.
-
As we'll see throughout this module,
-
we can have additional properties described
-
inside of our user class or any model they're in
-
that aren't particularly columns inside of our database,
-
but these column declarations inform Lucid
-
that this property should be matched
-
against a column inside of our database itself.
-
So that whenever we query using our user model,
-
it knows to pluck the ID
-
and plop it into this particular property.
-
These column decorators, as you can see right here,
-
also allow us to define additional things
-
about the column itself.
-
For example, our ID is our primary key,
-
essentially saying that the ID uniquely identifies
-
one particular record inside of our user model
-
and inside of our users table.
-
If we scroll down a little bit,
-
we're also gonna see column.dateTime.
-
This informs Lucid that we want to ingest
-
the createdAt and updatedAt for these two columns
-
as Luxon dateTime objects,
-
so that whenever we query a user,
-
these createdAt and updatedAt properties
-
will actually come back as Luxon dateTime objects
-
instead of just strings or traditional JavaScript dates.
-
Now, in case you're not familiar with Luxon,
-
it's a more up-to-date version of Moment.
-
If you recall back to the older Moment package,
-
that made it really easy to work with dateTimes.
-
This is the newer version of that,
-
and it's gonna do pretty much the exact same thing.
-
It's gonna make working with dateTimes a lot more simple.
-
Then just like we have on our ID column,
-
we're describing additional information
-
to these createdAt and updatedAt timestamps as well.
-
So we're describing that they should auto-create.
-
So anytime that we create a record using our user model,
-
both our createdAt and updatedAt properties
-
will auto-set themselves to the current dateTime,
-
and then auto-update will also auto-update by itself as well.
-
So anytime that we update a record using our user model,
-
our updatedAt will automatically update
-
to the current dateTime of which we're updating the record,
-
just automating some of that manual work
-
that we would have to do and remember about
-
whenever it comes time to work
-
with CRUD operations against our models.
-
CRUD meaning create, read, update, and delete,
-
in case you're not familiar with that acronym.
-
Okay, so there's a couple of properties on our user
-
within our database that we don't have added onto our model.
-
So we need to get those added.
-
First, we have our roleId.
-
So we'll come in here, we'll describe a brand new column,
-
and let's go ahead and declare roleId,
-
and that'll be of type number.
-
Now, as we type this out, you might notice one thing.
-
If we open up pgAdmin here
-
and take a look at our users table
-
and take a look at the columns on it,
-
our roleId is snakeCased, role_id.
-
The same is being applied to our full name,
-
createdAt and updatedAt here as well.
-
Let's go ahead and hide that back away.
-
The reason we're doing camelCased here
-
is that this is in line with the default naming structure
-
that Lucid uses to describe information to us.
-
As developers within a JavaScript environment,
-
it's a little bit more common
-
to work with properties directly as camelCased
-
as opposed to snakeCased,
-
but whenever it comes to database structure,
-
it's more common to work with snakeCased.
-
So they're keeping to the naming convention
-
used for the particular environment
-
that we're working within.
-
So by default, Lucid is going to expect
-
columns inside of our database
-
to be defined in snakeCased form,
-
so full_name, and then whenever we jump into the model
-
and our code therein, it'll expect it in camelCased,
-
so fullName.
-
If you were to have any one property within your database
-
that doesn't align to this naming convention,
-
you can add a configuration into your column decorator
-
and manually define the column name
-
for this one particular property.
-
So for example, if the column name inside of our database
-
was instead userName,
-
we could switch this to user_name,
-
and now Lucid would use user_name
-
to try and look up the value for our full name
-
within a database as user_name.
-
Now you can also change the default naming convention
-
used by Lucid,
-
so you can change the snakeCased within the database
-
and even the camelCased within your models,
-
and to propagate that everywhere,
-
you can make that change on the base model itself,
-
which all of our models will extend,
-
but that particular use case
-
is outside the realm of this lesson.
-
Just note that it is an option.
-
Okay, so we're done with our tangent
-
about naming conventions here for our models.
-
We know snakeCased in the database,
-
camelCased in the model.
-
We have one additional column to define for our user,
-
so @Column, declare,
-
and we have our avatar URL,
-
which will be a string.
-
Cool, now before we leave this model,
-
I'm gonna add that compose back
-
so that we don't forget about it,
-
along with our authFinder, just like so,
-
but don't worry about that at this point in time.
-
We'll cover that whenever we get to authentication.
-
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
-
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
-
Creating A Movie List Page3m 43s
-
Filtering A Query By Pattern Likeness7m 9s
-
Filtering Our List by Movie Status5m 47s
-
How To Apply A Dynamic Sort Filter To Your Query7m 12s
-
Joining 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
-
Join The Discussion! (0 Comments)
Please sign in or sign up for free to join in on the dicussion.
Be the first to Comment!