Defining Required Data with Seeders
Our database will have specific, non-changing, roles and movie statuses. In this lesson, we'll learn how we can quickly and easily create these records inside of our database using seeders.
- Author
- Tom Gobich
- Published
- Mar 02
- Duration
- 11m 11s
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 Required Data with Seeders
-
(upbeat music)
-
So as we defined in our last lesson,
-
we're going to want roles and movie statuses
-
to exist before anything else inside of our database.
-
Additionally, we're also going to have specific values
-
for those two tables as well.
-
We're gonna have specific roles inside of our application,
-
and we're also gonna have specific statuses
-
that a movie can have.
-
And the approach that we took to create records
-
in the last lesson by jumping into a REPL session
-
and creating them that way,
-
isn't a scalable way if you're working with a team.
-
If you're a single person working on an application,
-
that's fine, but if you have other members of your team
-
that's going to need to spin up a same instance
-
of your database and get populated quickly
-
with that same information,
-
that's where CEDARS come into play.
-
CEDARS allow you to define that information
-
that you're gonna need inside of your application.
-
You can run the CEDAR to create
-
that information automatically,
-
so that you don't have to have somebody
-
jump into a REPL session,
-
create that information themselves.
-
They can just run the CEDAR
-
and it will be automatically created for them.
-
So within our terminal,
-
let's go ahead and create a new CEDAR.
-
First, let's do node.ace_list
-
to see our available options.
-
We're gonna be making something,
-
so we'll look underneath the make section
-
and sure enough, there's a make CEDAR.
-
Node.ace_make_cedar.
-
Now, how you define your CEDARS is completely up to you.
-
You can either have a single CEDAR
-
that's going to make everything
-
that you need to get started with your application,
-
or you can divide individual CEDARS per resource
-
that you're gonna have
-
that you need to create information for.
-
So for example, we could create a single CEDAR
-
for our roles and a single CEDAR for our movie statuses,
-
or we could create a single CEDAR
-
to create both of those informations for us.
-
Since we're just getting started here,
-
let's just focus on a single CEDAR.
-
So let's just make a start CEDAR.
-
Okay, there we go.
-
So now we have a new CEDAR file
-
at databases/cedars/start_cedar.
-
We can go ahead and jump into our text editor
-
and jump into our database directory, CEDARS,
-
and there's our start CEDAR.
-
You'll see that it's exporting a default class
-
that extends a base CEDAR.
-
The base CEDAR is going to provide the functionality
-
to actually allow us to execute this,
-
and then it's providing an async run method
-
where we can create our movie statuses and our roles,
-
and we can use our models for both of these.
-
And we can do so similarly
-
to how we did in the REPL session.
-
So we can await, import our role from our role model, dot.
-
We have a create method that we can call,
-
and we just need to pass the values in.
-
So we could do name, administrator,
-
so on and so forth as we did in the REPL session,
-
but additionally, there's also a create many option as well
-
where we can pass in an array of those objects.
-
So if we had two roles to make,
-
we could pass in two objects to create them,
-
which matches exactly what we have.
-
So let's go ahead and do this.
-
So we could do name, user, and name, administrator,
-
or let's just do admin 'cause I find it rather hard
-
to type out administrator for some reason.
-
There we go, give that a save.
-
And if you'll recall back inside of our user migration,
-
so let's dive into our migrations there
-
and click on our users one,
-
we gave our roles for our users a default value of one,
-
which essentially, if we jump over to our start CEDAR,
-
is going to be the user role.
-
If we wanted something to fail
-
whenever we try to create our base CEDAR,
-
if one cannot be assigned to the user role,
-
we could explicitly assign the ID here
-
to cause that failure to happen.
-
Remember, whenever we inserted using the create method,
-
the ID was automatically assigned for us.
-
We didn't have to manually assign it.
-
So you do not have to manually assign this.
-
If there are instances though, where you want this to fail,
-
if it cannot be assigned a specific ID,
-
that's where you can explicitly assign the ID.
-
And since our user default value
-
is dependent on one being there,
-
we'll go ahead and do that here.
-
So we can explicitly assign our user role as one
-
and our admin role as two.
-
So let's pause here and take a look at exactly that,
-
because we already have a user role with an ID of one.
-
So we will expect this to actually fail.
-
So let's jump into our terminal.
-
Let's go ahead and clear things out.
-
Actually, before we do that,
-
let's scroll up a little bit so that we can see the command.
-
And this is going to be underneath the DB section.
-
We have dbced.
-
And by default, this will execute all CEDARs
-
within our application.
-
If we take a look at the help method for that,
-
we can run specific CEDARs.
-
So node.ace.dbced-help.
-
There we go.
-
You could specify individual files that you want to run
-
for a specific CEDAR file.
-
If there's just one particular one that you want to run,
-
you can do that.
-
There's also an interactive mode.
-
And if you have separate connections,
-
you could specify the connection as well.
-
Okay, cool.
-
So let's go and clear that out.
-
Let's do node.ace.dbced.
-
Again, expecting this to fail.
-
And there we go.
-
So it failed with our start CEDAR,
-
and it was trying to insert roles
-
with the column specified with the values,
-
returning ID, and the specific reason for the failure
-
is a duplicate key violates unique constraint
-
for that primary key ID.
-
I.e. it could not assign the ID of one to our user here
-
whenever it tried to create it.
-
If we were to get rid of that ID, give this a save.
-
Let's jump back into our terminal,
-
and let's run node.ace.dbced once more.
-
Everything should work, which indeed it did.
-
It completed our CEDAR.
-
But if we jump into pgadmin once more
-
and hit play to run this query again,
-
you'll see that these two bottom records
-
are the ones that were created from our CEDAR,
-
and they were assigned an ID of three and four,
-
skipping two because two was deleted already.
-
So if we did not have this first record here,
-
we would only have roles with an ID of three and four
-
within our database.
-
So that's where that explicitly assigning a value
-
inside of your CEDAR may come in handy.
-
But for the most part,
-
you should be able to ignore assigning IDs onto information
-
because the database will take care of that
-
automatically for you.
-
So since we're explicitly expecting our role
-
and our admin to have IDs one and two,
-
we can define this additionally using an enum.
-
So within our app directory, let's create a new folder.
-
So we'll do new file here.
-
We'll call the folder enums, and we'll call the file roles.
-
We can hit enter there,
-
and let's define an enum called roles.
-
Let's do our curly braces,
-
and let's define our user is going to equal one,
-
and our admin will equal two.
-
Let's go ahead and export default our roles.
-
Essentially what this will allow us to do is,
-
let's say we want to check
-
whether or not somebody is an admin.
-
Well, now we have an explicit reference
-
to what role inside of our application
-
specifies who's an admin.
-
So let's assume that we have a user variable here.
-
We could do user.roleID equals roles.admin
-
to discern if somebody is specifically an admin
-
inside of our application.
-
So now that we have that, we can jump into our CEDAR,
-
and we can assign the IDs using the enum.
-
So we can do roles.
-
Let's import that from our enums directory,
-
and let's actually scroll up a little bit.
-
So that did a relative import.
-
Let's go ahead and add a subpath import
-
for our enums directory.
-
So we can scroll down to our package.json.
-
We'll do this just above exceptions.
-
So we'll do #enums/*://appenums*.js.
-
Give that a save.
-
We can go ahead and give that a copy as well.
-
Let's dive down to our tsconfig,
-
and we'll do the exact same thing within here.
-
So we'll give that a paste,
-
and just wrap the value inside of an array.
-
Cool.
-
So now we can give that a save,
-
jump back into our start CEDAR,
-
and switch this to a subpath import.
-
So we can do #enums and get rid of the extension.
-
Okay, cool.
-
So let's dive back down to our role creation here,
-
and finish out our thoughts.
-
So roles.
-
And let's assign the ID here for our user as user,
-
and for our admin as roles.admin.
-
We can do the exact same thing within our users migration.
-
So if we go back to that file,
-
let's dive into our database,
-
migrations user,
-
scroll over to where we have that hard one,
-
and let's do roles,
-
import that from our enums roles.
-
And let's assign them the user role.
-
So not only does this make things easier to read,
-
we now know just by simply looking at it,
-
that our default role for our users
-
is going to be the user role,
-
but we also have a safeguard throughout our application
-
via our start CEDAR,
-
that we know explicitly that the user role
-
is going to have an ID of one,
-
otherwise it's going to fail to create,
-
and the same for our admin with the ID of two.
-
Okay, next we need to do the exact same thing
-
for our movie statuses.
-
So let's go ahead and jump back up,
-
and let's define an enum for that first,
-
so that we have that same safeguard going on for those.
-
So do movie_statuses.ts,
-
enum movie_statuses,
-
and let's do writing equals one,
-
casting equals two,
-
production equals three,
-
we'll have post production as four,
-
and then finally released as five.
-
And let's export default movie_statuses just like so.
-
So now we have a hard definition
-
on what status represents the movie as being written,
-
movie as being casted, cast members,
-
the movie is being produced,
-
so actually going through filming,
-
post production and released.
-
Let's jump into our CEDAR and actually get those created.
-
So I'm just going to condense down
-
our role create many here,
-
and we can do await movie_status,
-
import our model for that,
-
dot create many,
-
our array,
-
and we'll do objects for these.
-
Scroll down slightly here,
-
ID, movie_statuses,
-
there we go,
-
import that enum,
-
dot,
-
and we'll go in the same order as our IDs,
-
so we'll do writing first,
-
writing ID,
-
movie_statuses,
-
dot casting,
-
name, casting,
-
scroll down a little bit more,
-
ID, movie_statuses,
-
dot production,
-
name, production,
-
and we have post production,
-
so movie post production there.
-
Okay, and then lastly we have released,
-
so ID,
-
I've just kind of given up on writing movie_statuses,
-
and I'm just kind of fusing.
-
Auto-complete there to round it out for me there,
-
and then we'll do released for that value there,
-
and name released.
-
Okay, cool.
-
Give that a save,
-
everything should get their auto-commas added in,
-
and now we should be good to go.
-
So first, before we actually run this,
-
if we dive back into pgAdmin here,
-
we're going to want to clear out the roles
-
that we already have defined inside of this table,
-
and reset the IDs for this table as well.
-
So let's hide pgAdmin back away,
-
because we can't just simply delete them,
-
as that won't reset the IDs,
-
which use sequences to keep track
-
of what ID is next in the sequence.
-
So we can jump back into our terminal here,
-
hide our text editor back away, clear this out,
-
and let's use our node.ace.list
-
to list out our available commands,
-
and we have our migration commands here at our disposal
-
to do this for us.
-
So first, let's try refresh.
-
Essentially, that's going to roll back,
-
so we'll run the rollback command,
-
and then we'll run our migration.
-
So we'll run the run command, essentially,
-
automatically within that single command.
-
So we'll do node.ace.migration.refresh,
-
hit Enter there.
-
Okay, that reverted all of our migrations
-
and re-migrated them.
-
So if we dive back into pgAdmin and hit Run,
-
we no longer have any information inside of our database,
-
so we can hide that back away,
-
and let's try node.ace.db.seed.
-
And there we go, everything worked A-okay.
-
Let's jump back into pgAdmin, hit Run once more.
-
Okay, so I'm not quite sure what's going on
-
with pgAdmin there.
-
Let's go into View, All Rows again.
-
Oh, we probably just need to refresh everything
-
since we've re-migrated it.
-
So let's jump back up to our database,
-
right-click on that, and hit Refresh.
-
Okay, scroll back down,
-
and let's try again on our rules table.
-
So let's right-click that, View, Edit, All Rows.
-
There we go, okay.
-
So we just needed to refresh pgAdmin here to let it know
-
because it was trying to reference the old tables
-
that no longer existed.
-
So we just needed to give it a refresh there.
-
Okay, cool.
-
So we have our user record with one
-
and our admin record with two,
-
and we can jump into our movie statuses.
-
So right-click there, View, Edit, All Rows,
-
and we have all five of those here as well
-
with writing, casting, production, post-production,
-
and released, all with their explicit IDs that we expect.
-
Awesome, so everything's working there.
-
And since we created these using our Lucent models,
-
our createdAt and updatedAt
-
were automatically added in for us.
-
Awesome.
-
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!