Stubbing Fake Data with Model Factories
In this lesson, we'll learn how we can quickly and easily bulk-create dummy/fake data within our database for each of our Lucid Models using Model Factories
- Author
- Tom Gobich
- Published
- Mar 02
- Duration
- 13m 48s
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
Stubbing Fake Data with Model Factories
-
(upbeat music)
-
So to get started with querying
-
and building out information for our application,
-
it'd be really nice if we didn't have to go
-
and create hundreds of movies,
-
cast members and all that fun stuff ourselves,
-
but instead just had an automated system
-
to be able to easily spin up
-
as many of those particular items as we wanted to.
-
That's where factories come into play.
-
So within our terminal here,
-
if we do node ace list to see the list of the commands,
-
you'll see underneath the make section,
-
make factory.
-
A factory is essentially going to allow us
-
to stub a model with faker information or fake data.
-
So let's go ahead and create a factory here.
-
So let's do node ace make.
-
We're gonna need cynists before we actually have movies
-
or anything of the like.
-
So let's start with our cynists.
-
So let's do a factory
-
and let's do hyphen hyphen help here
-
to see the available commands.
-
You'll see that the first argument
-
is just going to be the model name.
-
So all that we need to do is node ace make factory
-
and to create one for our cynists,
-
we just do cynists.
-
I think I misspelled that.
-
There we go, cynists.
-
Hit enter there.
-
And that's gonna create a factory for us
-
inside of our database,
-
factories, cynists_factory.ts file.
-
So let's open up our text editor here
-
and let's take a peek at it and see what it is.
-
So let's go to factories, cynists factory.
-
Cool.
-
So you'll see that it's already importing
-
our cynists model automatically for us
-
and it's defining a factory specifically for that.
-
So it's returning back a callback function
-
inside of this define for our factory,
-
providing us faker information inside of here
-
and then returning back an empty object.
-
Lastly, calling build to build out the factory.
-
All that we need to do is define the information
-
for the model itself inside this object
-
that it's returning.
-
If we take a quick peek at our cynists model,
-
we have a first name, last name,
-
and headshot URL that we need to populate.
-
Everything else should be automatically taken care of
-
by either the database itself, which is our ID,
-
or by Lucid itself, which is our create_at and update_at.
-
Cool.
-
So let's dive back into our factory.
-
So start with first name.
-
We can reach for faker dot
-
and we'll have a number of different items
-
that we can select from.
-
So we have an airline, an animal, color, commerce,
-
company, database, data type, date, all that fun stuff.
-
We have image that might come in handy here in a second,
-
but if we keep scrolling down here, we'll see person.
-
Perfect.
-
That's exactly what we're looking for.
-
So we can take a look at what person offers
-
and look at that, we have first name right there.
-
So let's go ahead and use first name.
-
If there's a first name, we can probably assume
-
that's too going to have a last name.
-
So do faker person dot last.
-
Perfect.
-
And then I think the other one was a headshot URL.
-
Sure it was.
-
So we can do faker.
-
Let's see if person has a headshot URL
-
or anything of the like in here.
-
So let's see.
-
Bio job title prefix.
-
Nope.
-
It does not.
-
Though it does have a Zodiac sign
-
in case you have a need for that.
-
So cool.
-
Okay.
-
Let's try maybe image.
-
We saw that earlier on
-
and see a number of deprecated things within here.
-
So avatar right up here or avatar GitHub or legacy.
-
One of those would probably do just fine.
-
Maybe even Flickr.
-
We'll go ahead and use just avatar here.
-
That should serve our purpose well enough.
-
So we can give that a save
-
and we're off to the races.
-
Now our start seeder is specifically
-
for start information that our database needs
-
to get up and running.
-
Whenever it comes time to actually making use
-
of our application,
-
we're not going to want this faker information
-
to actually exist inside of our database.
-
So we'll define the faker information as a separate seeder
-
that we can use as an optional seed to get things going.
-
So we'll jump back into our terminal here
-
and we'll create a new fake seeder.
-
So node ace make fake seeder, just like so.
-
Oops, sorry.
-
Node ace make seeder, fake seeder.
-
Okay, there we go.
-
That one's right.
-
So now we have our fake seeder there.
-
And again, just like we did with our start seed,
-
all we need to do is create the information
-
that we want to exist inside of our database
-
inside the run method of the seeder.
-
So right in here.
-
And we can use our factory in place of our model
-
to create that information.
-
So we can await sin.
-
And you'll see within our autocomplete list here,
-
we have our sinist_factory.
-
Let's go ahead and click on that to import it
-
from our factory.
-
And let's see what our options are.
-
So if we do dot,
-
we'll see that we have both a create and create many method,
-
just as we do with our lucid model.
-
So we can use those to create information
-
inside of our database using the factory.
-
So let's click on create many there
-
because we're gonna want many sinist.
-
And the argument for this is just gonna take in
-
a count of the number of records that we wanna create.
-
So for now, let's just start it with 10.
-
Cool, so we can give this a save
-
and let's see if everything works.
-
So let's jump into our terminal here.
-
Let's clear this out so it's a little cleaner.
-
And let's try to run using the same command
-
that we ran last time.
-
So that's node, ace, db, colon, seed.
-
By default, this is going to run all of our seeders.
-
So if we hit run, you'll see that we get an error
-
because it cannot create another role
-
with an ID of one or two.
-
So that's gonna violate that unique constraint
-
on the primary keys.
-
So whenever we run this in the future,
-
although our fake seeder did complete successfully,
-
we're gonna want to use that files argument
-
to explicitly define that we just wanna run the fake seeder.
-
But since that did complete,
-
we should be a-okay to keep it as is for right now.
-
So let's hide that away
-
and just keep that in mind for future reference.
-
Dive back into pgAdmin
-
and we can right-click on our sinists,
-
go down to view edit data and click on all rows.
-
And voila, we have now 10 fake sinists,
-
each with a first name, last name,
-
and some form of a headshot URL.
-
Awesome, so everything seems to be working a-okay there.
-
Cool, so let's continue onward
-
and continue defining our factory.
-
So we'll do node, ace, make factory.
-
We have explicit values that we have within our start seeder
-
for both our roles and our movie statuses tables.
-
So we're not gonna need fakers for those
-
because we already have real-world data
-
that we want our application to use
-
populated within there from that start seeder,
-
which leaves us with our users, our sinists,
-
which we've just created a factory for, and our movie table.
-
Now, also remember that we have crew movies
-
and cast movies tables inside of our database
-
that serve as many-to-many pivot tables.
-
We don't need those defined as models
-
because they'll be able to be joined together
-
via the relationship that we'll define in the next module.
-
So we can ignore those for now
-
and just focus on these models that we have here.
-
So let's do a factory for our movie next.
-
Okay, cool, so we have that one created.
-
Dive down into there.
-
And we have a number of different properties on our movie,
-
so I'm just gonna drag our movie model over here
-
onto the right-hand side of our screen
-
and hide our explorer away using Command or Control + B.
-
Now, this model in particular
-
has a number of different relationship-based IDs
-
specifically on it,
-
and we haven't defined anything relationship-based yet,
-
but these IDs are required.
-
So for right now, for our factory,
-
we're just going to stub these with hard values.
-
So for our status ID,
-
we actually have this within the enum,
-
so we can put a specific hard value here if we wanted to,
-
so we could import our status ID, enum,
-
movie status is right there.
-
And for right now, let's just put them all in writing.
-
And then we have our writer ID.
-
We'll just hard-code those to one,
-
and our director ID as two,
-
so that there's a slight difference between the two.
-
And then we should be good to continue onward
-
with the rest of our Faker information
-
for the rest of the properties.
-
We'll circle back whenever we get to relationships
-
and fill these two in with relationship-based information.
-
Cool, so let's do our title next,
-
and we can reach for Faker.
-
And let's see what we have.
-
Let's see if there's a movie in here.
-
I doubt it, but you never know.
-
We have music.
-
I don't see movie.
-
Okay, yeah, so I don't see anything from movies,
-
but we could probably use music as that's fairly close.
-
It's probably the closest thing
-
that we have available in here.
-
So we'll go ahead and click on music,
-
and let's see what we got there.
-
So we have genre and song name.
-
So let's go and do song name.
-
That'll serve our purpose well enough.
-
And next we have our slug.
-
Now in our final application,
-
we're gonna want our slug to be a URL safe representation
-
of our title.
-
For right now, we don't have anything for that in place,
-
so we can use Faker to just add in some slug within here
-
so that we have that populated.
-
Later on, we'll automate that process inside of our model
-
so that anytime that we save a new record
-
inside of our movie table,
-
our model will convert the title
-
into a URL safe representation for our slug.
-
For now though, we will just use Faker,
-
and we can use the string option
-
and just plop a UUID in here for right now.
-
That should serve as a URL safe version of a string
-
that we can plop on the slug for right now.
-
Okay, and then we have our summary.
-
For this, let's just put some lorem on it,
-
and let's just put it to a single sentence.
-
Okay, and then we have our abstract,
-
which is a long form string.
-
So we could put whatever we want in there.
-
So let's do abstract.
-
Lorem will probably be the most appropriate,
-
so we'll do that.
-
And for this one, we can do paragraphs,
-
and we'll just let it put whatever it wants inside of there.
-
And then we have our poster URL.
-
So Faker, just like our headshot URL,
-
this will be an image dot,
-
and let's just use pick some photos for this one.
-
Okay, and that should do it.
-
We're now down to our created at and updated at,
-
which our model will take care of for us.
-
So that should be our movies factory.
-
We can close our model and open back up our explorer
-
with Command or Control + B.
-
And lastly, let's create our user factory
-
before we do anything else.
-
So let's jump back into our terminal,
-
node, ace, make, factory, user.
-
There we go.
-
Jump back into our text editor,
-
jump into our user factory,
-
and let's define the properties for that.
-
So we can drag that back over to the right-hand side
-
as a reference, close our explorer,
-
and scroll down just slightly here.
-
Again, we have our role ID, which uses a relationship.
-
For right now, we'll just hard code something in here.
-
So we can do roles to import our rolling num,
-
and we can assign a user,
-
or we could leave this out altogether
-
and just have the database's default value
-
auto-populate this for us,
-
but so that we don't forget about it,
-
let's leave this in here as an explicit value.
-
And for this one, we have full name.
-
So we can do full name as faker,
-
leave person was the property that we used on the other one,
-
and there should be a full name option in here too.
-
There we go.
-
Then we have our avatar URL.
-
So we'll do faker image, and let's do avatar.
-
And then we have an email.
-
So faker, the internet property
-
should be what we want for that.
-
And there's an email right there.
-
All right, we'll scroll down a little bit.
-
Okay, looks like the last thing that we need is our password.
-
So we'll do password faker.
-
I bet you internet's gonna have that.
-
So we'll do internet dot, yep, sure enough,
-
password, cool.
-
Now we haven't discussed this at all yet,
-
but if we take a look at our user model,
-
scroll up to the top, it's using this auth finder right here
-
and that's being composed into our user model.
-
Remember composed just kind of joins together
-
two classes that we want to extend
-
and it's composing that with the base model.
-
So everything that provides us lucid functionality.
-
This auth finder is going to add in a hook
-
so that anytime that we save the model instance,
-
it will check to see whether or not
-
the password value has been changed.
-
If the password value has been changed,
-
it will hash it and secure it inside of our database
-
so that it's not stored in plain text automatically for us.
-
So let's jump back into our factory
-
and whenever we create our user, we'll see exactly that.
-
So we'll get some plain text value provided into faker here
-
and then our system will automatically hash it
-
and secure it inside of our database.
-
So let's jump back down to our fake cedar
-
and let's await, we'll do our movie factory here,
-
dot create many.
-
Let's just create three of those
-
and then await user factory dot create many.
-
And let's create five users.
-
So we can give that a save, jump back into our terminal.
-
Let's clear this out and let's run node ace eb seed
-
hyphen hyphen files equals.
-
And then we want to point it to the particular file path
-
that we want to run, which is our fake cedar.
-
And this will allow us to only run our fake cedar
-
instead of our start cedar.
-
So we can do database cedars, fake underscore cedar,
-
TS, hit enter there and there we go.
-
It just ran our fake cedar and it completed successfully.
-
Now you'll note that we had already run this
-
with our Sinist factory.
-
So our Sinist factory has not run twice.
-
So we'll have 20 Sinists inside of our database,
-
but we'll only have three movies and five users
-
because those two have only run once.
-
So if we dive back into PG admin,
-
refresh our Sinist by hitting play button right there,
-
we should now have 20, which we do indeed.
-
We can go over to our movies, right click on that,
-
view edit data, all rows.
-
We should have three of those, sure enough.
-
And remember we hard coded the status ID, writer ID
-
and director ID, so those will all be the same,
-
but we do have our dynamic movie titles,
-
our slugs, which we set to the type of GUID,
-
which looks right, some lorem summary and a lorem abstract.
-
And if we continue scrolling over,
-
we should lastly have our poster URL, sure enough.
-
And Oh, forgot all about the release step,
-
but that is nullable, so that's a okay.
-
Okay, cool.
-
So let's scroll back over and let's lastly run our users.
-
So let's right click on that, view edit, all rows.
-
There we go, we have five of these
-
with the full name populated.
-
They have an avatar URL, there's their email
-
and there is their secure password.
-
It was secured using script,
-
which is the default hashing mechanism.
-
So we are unable to see the plain text value
-
that was assigned into Faker inside of our database,
-
making our passwords nice and secure.
-
You never wanna store your passwords in plain text.
-
If your database ever becomes compromised,
-
their password is also compromised.
-
Always make sure you never store your passwords
-
in plain text, okay.
-
And then we have our created that and updated that there.
-
So everything looks good.
-
I'm gonna go ahead and put the release that
-
inside of our factory so that we don't forget about it.
-
Again, let's see, that was our movie factory.
-
Okay, so released.
-
And we can just put that the null since it's nullable.
-
And the status ID is being set to writing
-
instead of released at this point in time anyway,
-
so that matches with what we would expect.
-
Okay, cool.
-
Now, since our fake cedar specifically creates
-
fake information using our factories,
-
we don't want this to actually execute within production.
-
So we can use an environment specification
-
inside of the cedar to specify that we only want it to run
-
in certain environments.
-
Specifically for this use case, probably just development,
-
but we could also include testing if we wanted to.
-
So we're gonna add a static property onto the class here
-
called environment and set this to an array.
-
Inside of this array is where we define the environments.
-
So first, we're definitely gonna want this to run
-
within development so that we can create the fake data
-
to actually use throughout development.
-
If you wanted it to also be executable within testing,
-
we can include testing there as well.
-
The one that we don't want to include is production.
-
So be sure that you leave that out of any faker-based cedars
-
so that you don't have fake data
-
out in your production environment.
-
So these are the only environments that the cedar will run
-
whenever we attempt to use node-ace-db-seed.
-
In fact, for right now, I'm gonna go ahead
-
and just leave this as development.
-
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!