00:01
So let's go ahead and focus on getting our database set up next. So it's going to be our models, migrations, factories. So we'll stop our application, clear our terminal out.
00:08
And the very first thing that we actually need to do is finish out our user model. So whenever we ran our AdonisJS project creation, we were given a user model and then Jumpstart altered it
00:18
and added a couple more things on top of it. So what we want is a factory for our user model in addition to the model itself.
00:26
So what we want is a factory for our user model in addition to the model and migration that were already created for it. So instead of a terminal, we'll do node, ace, make, factory
00:36
and call it user there to create our user factory. The next thing that we want to do is create a model, migration, and factory for both our book and genre entities.
00:44
So we'll do node, ace, make, and we'll do model for our book and do hyphen m to create a migration for it, f to create a factory for it as well.
00:53
And then we're not doing any CRUD-based operations for these in this series, but if you were and you wanted to create a controller on top of it, you could also do C there as well.
01:02
Since we're not doing CRUD operations, we'll go ahead and leave that out here. So we'll hit enter there to create a model, migration, and factory for our book and we'll do node, ace, make, model for our genre
01:12
and do hyphen mf for that one as well. The last thing that we need is a migration to bind our book to a genre. And that is going to be a many-to-many relationship, so we need a pivot table to join them.
01:22
So we'll do node, ace, make, migration, book, underscore, genre, and hit enter to create that. The reason why we're doing book, underscore, genre
01:32
is to stick with AdonisJS's pivot table default naming convention. By default, AdonisJS will expect an underscore concatenation of the two entities we're binding with our pivot table in alphabetical order.
01:42
So our book would come first, followed by our genre. And then they're both going to be singular. Now, by default, something to watch for, the migration will create it as plural,
01:51
so we will want to alter that whenever we get to that step. Okay, let's go ahead and jump back into our text editor and we'll start with our migrations. So we'll jump into our database, migrations.
02:00
Again, as you'll see here, we already have one for our users and we're going to be searching based off of a full name string. So we're all set here as our user is already populated with that.
02:09
And then Jumpstart, in addition to making a few user model alterations, has also given us an email histories table, a password resets tokens table,
02:18
as well as the remember me tokens table. So we can go ahead and jump on down to our books migration because what we want to do is bind this first to our user
02:28
that's going to serve as our authors. So we'll do table integer user ID, make this unsigned and then have it reference so that we get a foreign key created for it.
02:37
The users table ID column, and then we'll make this not nullable. And then when deleted, so when our user is deleted,
02:45
we'll go ahead and have the book cascade delete along with it. In addition to that, we want a table string for the book's title. I'm going to go ahead and omit the column lengths off of all of these
02:54
just to simplify everything here a little bit further. And we'll make that not nullable. And then we'll do another string here with a blurb and a table dot.
03:02
Let's do this as a text for an excerpt, if I can spell it. There we go. The excerpt is going to be like the first chapter of the book and then the blurb is going to be about the book.
03:12
So like a summary. And then in addition to that, we can also do a timestamp for the book's publication date. So we'll do publish at there.
03:20
Okay, so that should be all that we need there for our book migration. Let's do our genres next. For this one, all we need is a string with a name and we can make that not nullable. And then in addition to that,
03:30
we now need to bind it to our books via our pivot table. So the first thing that we're going to want to do is, again, stick with the AdonisJS defaults.
03:38
So we'll switch that from plural to singular for our table name. So that is book underscore genre. And then we'll add in our book integer column.
03:46
So integer book underscore ID. Make that unsigned. References our books ID column. Make that not nullable.
03:54
And then we'll go ahead and cascade the deletion on this as well. Lastly, we need our integer for our genre ID. That too will be unsigned.
04:04
It's going to reference our genre's ID. Make that not nullable. And then we can go ahead and cascade that as well. As if the genre doesn't exist, then the book won't belong to that genre.
04:13
Now, it doesn't make sense for a book to belong to the same genre more than once. So in addition to our columns there, we can also add in a composite unique constraint
04:22
against our book ID and the genre ID to make sure that we don't get duplicates in this table. Perfect. Let's go ahead and run our migrations real quick just to make sure that we got everything right.
04:32
So node ace migration run. All right, perfect. Everything ran there A-OK. So we're good on that front. Our next step in this process is filling out our models.
04:42
As in order for us to fill out our factories, it's going to rely off of the types defined via the model. So we'll jump into our book first as we didn't need to add any columns
04:52
or alter any columns on our user. So we'll just need the relationship defined there. And for our book, we have an at column. We can declare this is a user ID of type number.
05:01
Then we have a column declare title of type string. Then we have another column declare blurb of type string or null.
05:09
And then we have a column declare. This is excerpt. I have a hard time saying and spelling that for some reason. And that is a string or null.
05:18
And then we have a column. And we can set that as a date time. Declare publish at as a lux and date time or null. Perfect.
05:27
While we're in here, let's go ahead and define our relationship. So we have our user relationship. So that is a belongs to. So import that from AdonisJS Lucid ORM
05:36
and use our user model for that relationship. Declare. And I'm going to call this user just to stick with our user ID name there even though it will serve as our author.
05:45
And then we'll do belongs to type of user. And then we'll get a red squiggly on that because that needs to be an import type. So we'll do command down on that squiggly and switch that to an import type.
05:55
All that did was add this type right there before the belongs to import in case you don't get that autocomplete option. In addition to that, we also have our many
06:05
to many relationship between our book and its genre. So we'll declare genres as a many to many type of genre.
06:15
And our book model should now be all set. Perfect. Let's now move on to our genre. So for this one, we just have a column declare name of type string.
06:25
And then this one too has a many to many relationship to our book model.
06:31
Declare that as books many to many type of book. Okay.
06:37
And then again, we need to command dot on that to switch that import to a type import. Perfect. Lastly, let's do our relationship for our user.
06:46
Command dot there to fix up all of those spacing issues. And I'm going to put this before the methods.
06:52
So just after our columns, Jumpstart added some methods onto this user model for authentication. So we'll declare this as has many and has many books.
07:02
So we'll use our book model there. Declare books as type has many type of book.
07:09
And then again, command dot to switch that to an import type. Perfect. So our relationships are all set up now as well as all of our column properties.
07:18
So we're ready to move on to our factories. So for our book, what we want to do is within the return object here,
07:24
define the same columns that we have defined on our model that we want filled out with fake data from our factory. So that would be like our title.
07:32
And for that, we can use Faker, which is provided to us via the callback. So Faker dot, and we should have book as an entity type.
07:39
And we can reach for title to create a fake title for our book. Now, there's no like blurb option within Faker for books.
07:46
If we go to Faker book dot, you'll see that we have author, format, genre, publisher, series, and title.
07:51
But we can still kind of get like a blurb like thing by using commerce. And then there is this product description. Technically, a book is a product, right?
08:01
So it still kind of fits. And then for our excerpt, we have just lorem.
08:07
That would make the most sense there as nothing within Faker is going to give us a full first paragraph of a book. So let's do paragraphs here and stub it with two paragraphs worth.
08:16
It's a very short chapter, but yeah, it'll do. And then for our publish at, there is Faker dot date. And then we can just set this to sometime in the past.
08:25
But there's plenty of other options if you want to include future dated books as well within your data set. But I'm just going to use past here and we will get a red squiggly on this. Actually, the red squiggly is coming up here.
08:35
But the same thing is true. It's because it's trying to assign a date to our date time. So we want to convert this to a Luxon date time.
08:43
So we'll import Luxon there and do from JS date and pass the Faker date through that.
08:50
So that it's converted to a Luxon date time to fit with our type within our book model. While we're here, we can also go ahead and set up our relationships since the factories do exist.
08:59
So we'll do relation user, provide a callback in that returns back our user factory. And this also has a relation to the genres and we'll provide it our genre factory for that. Perfect.
09:09
So now we're done with our book factory there. Move on to our genre next. This one will be short and sweet. Just have a name, Faker dot book. And then we saw previously we have a genre option there.
09:18
And then this one has one relationship to its books. So we'll just return a callback using that book factory for that. So whenever we create a relationship through the factory,
09:27
it's going to use the factory provided via the callback to actually create the instance of the related book. Lastly, we have our user factory here.
09:35
So we will return the full name, Faker dot person dot. And there should be a full name option in there. Then we have the user's email.
09:44
So we can use Faker dot internet dot. And there should be an email option within there. And then lastly, we have the user's password.
09:51
Now for this, I'd recommend not using Faker because it's actually going to use a fake value to populate the user's password.
09:58
And there's going to be no way for us to get that password back beyond resetting the password for the account.
10:03
Since we're just on local here, it makes sense to just give ourselves some known password that we can easily enter in case we need to enter in a preexisting user's account.
10:11
So we're just going to make all of our user's passwords something. So now anytime that we enter in a user's email, their password's always going to be something.
10:19
And then our user model, whenever this Faker creates it, is going to secure it inside of our database so that it doesn't actually read as something for us.