Playing Next Lesson In
seconds

Transcript

  1. So it'd be great if we actually had real movie titles inside of our application using faker information rather than just song names

  2. because now our application feels more like a song database rather than a movie database. So I've taken movies listed from the National Film Registry and I've normalized this into a JavaScript

  3. or TypeScript array of objects containing a title and a released year. So today we're gonna take this list and use it to seed our information inside of our application. So let's go ahead and hide our browser back away.

  4. Now we could use this list of titles directly inside of our Model Factory, but it would be great to also be able to generate out random movies that are future dated and the like

  5. since our list stops at 2017. So instead what we'll do is just use it directly inside of our fake seeder. It will just generate out one movie per record that we have inside of this list.

  6. Oops, I actually forgot to copy that list. So let's dive back into this gist that I have here, click on raw and let's Control or Command + A, Control or Command + C to give that a copy. Okay, now we can hide that back away.

  7. And inside of our database directory, let's go ahead and right click, new file, and let's create a folder. We could call this data, we could call this faker. I'm just gonna call this data for now, movies.ts.

  8. And let's go ahead and paste that list in and give it a save so that it formats. Cool, you see up here at line one, we're exporting const movies. So within our fake seeder, we can import that

  9. and let's make use of it inside of a separate method within here. So we'll call this async, we'll make it private and we'll call it create movies. Okay, now we still wanna make use of our Movie Factory.

  10. So we'll await movie factory.createMany and we'll wanna create one movie record per movie that we have inside of our data list here. So we wanna import our movies, so we'll type out movies

  11. and hit tab to auto import that from database data movies and provide it its array length. Now, currently this would create one movie with any random song name as its title.

  12. What we wanna do instead is tap into this prior to its actual creation. And with this tap method, we can provide a callback function that's provided a row, which in this case

  13. is going to be an instance of our movie model class. It'll also provide us a factory context and a factory builder. So within here, we can do row, provide that as a callback method and now if we type out row,

  14. we'll see that this looks exactly like a typical model would so we can type out title and overwrite the title prior to this record being persisted into the database

  15. because tap is run just before it is persistent. So within our tap callback method, what we wanna do is grab the index of the current movie that we're on.

  16. So let's do let index equals zero. We'll want to index plus plus at the end of this to increment that. We can go ahead and plop our movie into a variable.

  17. So we'll do const movie equals movies.index and then we can set the current movie title by calling movie.title. Now we can do something similar with the release data as well. Since we have the released year,

  18. so we can use faker by extracting that out of our factory context just like so. We can do faker.date. We can use the between method to start dates that the random date should be between.

  19. Since we only have the released year, we can set this to a random date within that year so that all of our movies aren't using the same month and day as we're looping over them here.

  20. So we'll say from and let's grab an instance of a LuxonDateTime object set to the movies released year. So we'll say released equals date time,

  21. importing that from Luxon just like so. So we'll say date time dot, and we can just set this to now and then overwrite the year to our movie.releasedYear.

  22. Cool, so now this object is set to a LuxonDateTime set to the current movies released year. So meaning we can do released.startOf

  23. to go to the start of the year and then to released.endOf to go to the end of the year. Now we have a couple of issues here to fix.

  24. Firstly, faker.date is going to return back an actual JavaScript date, whereas our released.dat is expecting a LuxonDateTime.

  25. So we can wrap this in dateTime from JS date to ingest the faker.date in as a LuxonDateTime. Give that a save. And now we have our second issue,

  26. which is that faker in the from and to is expecting a JavaScript date or a string or a number. So we have a couple of options there. We can either do toISO, toString, toFormat,

  27. or we can just do toJSDate to convert that to a JavaScript date. We'll just go ahead with that one, cool. So now as we loop through the movies that we're creating,

  28. one per record inside of our movie array here, we'll increment our index so that we can get an instance of the movie that we're currently on inside of our tap callback,

  29. overwrite the record's title with the actual movie title, and overwrite the released out with some random date between January 1st and December 31st

  30. of the current released year for that particular movie. Before we give this a go, let's go ahead and move our other movie factories, creation calls inside of our createMovies

  31. so that it's true to the method's name. So we'll go ahead and plop these down at the end after we run through our real movies, cool. We can also clean this particular movie factory up a little bit.

  32. So instead of merging in every time that we wanna create a movie that's released, we can instead specify a state directly on the movie factory and then just call that state here so that we don't need to merge the state in

  33. every single time. So within our movie factory, we can scroll down here, do .state, give the state a name. So we could do released. And then the second argument to this is going to be very similar to the tap method.

  34. It's going to provide us in the row for the movie prior to it being persisted into the database. And then we also get the factory context and factory builder as well. So we can extract faker out of this too.

  35. So we can do pretty much the exact same thing that we just did inside of our fake cedar to specify a movie has been released for whatever factory we're running this with.

  36. So we could do row.statusId to set that to movieStatuses.released,

  37. and then row.releasedAt equals dateTime.fromJSDate. We need to import that from Luxon. So dateTime, hit tab to auto import that from Luxon,

  38. just like so. And then we can use faker.date. And set this to sometime in the past since the movie will have been released. We can also do one for releasing soon.

  39. So if we give that a copy and a paste, we could do releasing soon, or just soon if you want to keep that nice and short. We can keep the movie status to released, and this will give the scope that we defined

  40. on our movie model a nice test case. So we can set the release date to soon rather than sometime in the past so that our movie status is set to released, but the release date is still sometime soon there

  41. in the future. So although the movie is set to released, it's not actually physically released because the release date has not been met yet. Let's do one more. So let's do one for post-production here.

  42. So we'll do state name of post-production, set the movie status to post-production, and we can leave the faker date to soon there. Okay, give that a save, jump into our faker cedar,

  43. and now we can replace this merge call here instead by applying one of our states. And for this, we just need to provide in the state name. So here we were creating released movies,

  44. so we'll call apply there with released as the argument, and now we're creating our released movies without having to merge in information for that. We can give that a copy, paste it two more times

  45. because we also have releasing soon as well as post-production that we can create as well. So we give that a save. Lastly, we need to actually call our create movie method. So up here within our run method,

  46. all we wanna do is await this create movies, just like so. Awesome. Now we're ready to go ahead and roll back our database, rerun everything and reseed our database as well.

  47. Now, one thing to note before we do that though, is that you don't wanna place this data directory inside of cedars because whenever we run our seed command, Athonis JS is going to try and auto import

  48. whatever cedar files we have within here, and if it's not an actual cedar, it's going to result in an error. So we've placed our data directory directly underneath database here for a very particular reason,

  49. even though we're only using it inside of our cedars. Okay, so let's go ahead and hide our text editor back away. Let's reset our database. So node ace migration reset. This is going to roll back

  50. all of the migrations that we have, regardless of what batch number it was run within. Okay, let's go ahead and node ace migration run to rerun those migrations.

  51. All right, and lastly, let's go ahead and node ace db seed. And we've run into an error. Now, here it's saying it cannot insert into users and specifically it's complaining

  52. about the user's role ID foreign key constraint. Essentially, we're trying to insert into users because our fake cedar is running prior to our start cedar.

  53. So our roles don't actually exist at the time that we're trying to insert into our user's database. So what we need to do is specify

  54. that we want the start cedar to run before our fake cedar, so that those roles and the information that we're creating inside of our start cedar actually exists whenever we get to our fake cedar.

  55. So let's go ahead and node ace migration reset to roll back all of our database migrations because our start cedar did succeed. So we wanna get rid of that information

  56. to test to make sure that our fix here works properly. Dive back in the Visual Studio Code. And by default, AdonisJS is going to run these similar to migrations. It's going to run them in alphabetical order

  57. or whatever order they're displayed in using a natural sort. And we want our fake cedar to run after our start cedar. So we'll just do 01 with an underscore there. And now we'll jump down to our start cedar.

  58. And we're always going to want this to run first. So we'll do 00. So now our start cedar is naturally sorted before our fake cedar. So AdonisJS should now run them in the order that we want them to.

  59. So we can hide our text editor back away. We've already reset our database. So let's go ahead and re-migrate it. So node is migration run. Cool, let's clear that out. And let's go ahead and seed our database once more.

  60. There we go, awesome. So it ran it in the order that we wanted it to and everything completed successfully. All right, let's go and run our server. So npm run dev, jump back into our browser, jump over to our application and look at that.

  61. Wow, we can keep scrolling and scrolling and scrolling and we're just gonna have a bunch of movies and even better yet, we now have actual movie titles. Some of these are gonna be song names, but for the most part, what we have here

  62. are actual movie titles that we're working with now. Awesome. So now we need to take care of the number that we're displaying, but we have plenty of movies to work with now at our disposal.

Tapping into Model Factory States

In This Lesson

We'll dive a little bit deeper into Model Factories by introducing factory states. We'll also learn how we can use the tap method to alter a factory result prior to it persisting into the database

Created by
@tomgobich
Published

Join the Discussion 0 comments

Create a free account to join in on the discussion
robot comment bubble

Be the first to comment!