How To Create Factory Relationships from a Pool of Data
In this lesson, we'll learn how we can refactor our fake data seeder to allow us to assign cast members and crew members to our movies via our many-to-many relationships from a single pool of cineast records.
- Author
- Tom Gobich
- Published
- Apr 05
- Duration
- 13m 55s
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
How To Create Factory Relationships from a Pool of Data
-
[MUSIC]
-
So let's say that instead of creating a brand new Cineast for these,
-
we instead want to use the pool of Cineast that we have and
-
assign them for the relationship from that pool.
-
Essentially reusing Cineast as we go about movies so
-
that we have multiple Cineast assigned as cast members or
-
crew members to multiple movies rather than just one by one as we have here.
-
Let's hide PGM back away and let's remove what we have so far.
-
Getting this back to how it was prior to last lesson.
-
Okay, let's put a couple line breaks here so
-
that we can focus on just this one line for right now.
-
Let's plop the results of this factory's creation into a variable.
-
So let's do const.
-
And since this is the only movie factory that we're not doing anything to,
-
we're not applying any states, not tapping through it or anything like that.
-
Let's put these in a variable just called our default movies,
-
since it's using all the defaults.
-
This should be an array of movie models as you can see here.
-
What we can do is actually just use these models now as actual relationships
-
to create relations randomly for
-
the Cineast pool that we're providing into our create movies method.
-
Okay, so we're going to get a pool of promises.
-
So let's give ourselves a place to house those.
-
So up here at the top of our create movies method, let's just do const
-
promises equals an array and we can specify the type for this as a promise any array.
-
Okay, we don't really care what the promise is going to return at the end of
-
the day, we just want to make sure that we can wait for
-
all of them to finish before we return out of this method.
-
Okay, so let's loop over our default movies like so, and
-
we'll have an individual movie here.
-
We'll do const crew Cineast equals.
-
And let's create ourselves a utility to grab a random number of Cineast out of
-
our Cineast array.
-
So let's create a private method called get random that accepts in an array.
-
We'll need a type for this array so
-
that we can return back the same type that we provide in.
-
For that, we'll need to add in a type variable to our method itself, and
-
we'll call that T.
-
Then we'll provide the number to plug out of the array so
-
that we can get any random number that we want.
-
First, let's shuffle our array.
-
So we'll shuffle equals array.sort 0.5 minus math random.
-
Then with our shuffled array, we'll go ahead and return shuffle.slice,
-
start at the zero index, and go to the pluck number that we've provided it.
-
So now if we scroll up from our Cineast array,
-
we should be able to do this.get random, provide in our Cineast array, and
-
say that maybe we want to pluck five out of that array.
-
If we take a look at our crew Cineast type, we now have a Cineast array.
-
Awesome.
-
Well, in terms of creating our relationship,
-
what we really care about are just the IDs.
-
So let's do crew Cineast IDs there, map over our results,
-
pluck out the ID, and return that ID.
-
So now our crew Cineast IDs should be a number array, which it is.
-
We can go ahead and give this a copy and
-
do the exact same thing for our cast Cineasts as well.
-
For this, so that we can discern them, let's do three.
-
Okay, with the individual movie that we're looping over,
-
we can now grab the relationship, so related crew members dot, and
-
attach in the random array of IDs that we've grabbed.
-
So that would be our crew Cineast IDs like so.
-
And that's how we can create records using a many to many relationship.
-
From the movie model instance, we grab the relation we want to create records for,
-
and attach IDs for that relation.
-
And it will populate our many to many pivot table with the movie's ID,
-
as well as each one of the relation IDs that we provide it.
-
In our particular case though, we have pivot data we also need to provide.
-
And this does complicate the call a little bit.
-
But if we take a look at a hard coded version,
-
we'll see that it's still relatively straightforward.
-
So instead of providing an array of IDs, we'll now want to provide in
-
an object where the key is the ID.
-
So if we want to bind a Cineast with an ID of one to the movie that we're working
-
with, the key would be the ID of one for that Cineast.
-
And then the value for this key is going to be the pivot table data that should be
-
created for this Cineast with an ID of one, and they're binding to this movie.
-
So that would be their title of, let's say, camera operator,
-
as well as their sort order of zero.
-
And then we just do that same thing over and over again for
-
each one of the Cineasts that we want to bind.
-
Ignore my poor formatting there, but say if we want to then attach a Cineast with
-
an ID of two, we do that exact same thing with a key of now two.
-
And that will bind both a Cineast with an ID of one with this particular pivot table
-
information, and a Cineast with an ID of two with this pivot table information.
-
So we could change that up to make them unique per each one, and
-
it would account for that accordingly.
-
So what we would want to do is do that in a loop based fashion for
-
our loop of IDs here.
-
So we'll scroll down, get rid of the object that we have here so far.
-
And the easiest way to do that would be to reduce through the array.
-
So we'll do crew Cineast IDs, reduce.
-
We'll have our overall object that will create the relationships,
-
as well as the current ID that we're working on.
-
And then we're also going to want the index so that we can increment our sort.
-
Okay, we'll return that back and instantiate the default value as an object.
-
So for our object, we'll bind in the current ID we're working with and
-
have that value equal our intermediary table data.
-
So we could have a title of say camera operator and
-
our sort order of the current index.
-
Then we will return back our new object, give that a save for our formatting.
-
And we do have a couple red squigglies going on still.
-
So first we have already used the variable index,
-
that is if we scroll up right there.
-
So we'll just call this i.
-
I think we're all relatively familiar with i at this point.
-
So we'll move forward with that.
-
And then second, we're getting an implicit any type here.
-
So all that we need to do to fix that is provide a type to our reduce method.
-
So we'll do two angle brackets there.
-
And let's hover over attached and
-
that will provide us the type that we're working with right here.
-
So let's give that a copy and paste it in.
-
Now we don't have a model object imported.
-
So let's just type model object, hit tab to auto import that and
-
we should be good, awesome.
-
So now we're looping over each one of our crew Cineast IDs,
-
adding in an object where the key is the individual ID and
-
the object is the pivot table data that we want created with that ID.
-
And then returning back that new object,
-
which will then be attached into our movie via our crew members relationship.
-
We'll want to do this several times over for
-
each one of the movies that we're creating.
-
So let's extract this out into a helper method as well.
-
So we'll give this a copy, scroll down, and let's do private attach crew members.
-
We'll paste that in.
-
And what we want to do is provide in a movie of type movie,
-
provide in our IDs array, which will be a number array.
-
And then for our titles, we'll create an array and
-
pluck a random title out of that array for the Cineast that we're binding.
-
And we just need to update our crew Cineast IDs to just IDs now,
-
give it a save to fix that formatting.
-
And we can go ahead and just return that back and this will be an async method.
-
Let's also have this method randomly pluck the IDs for
-
us as well to just get rid of one extra duplicate line.
-
So attach random crew members and instead of IDs,
-
let's have this be our actual Cineast array, just like so.
-
Okay, let's scroll up to where we are grabbing random crew Cineast IDs.
-
Give that a copy, scroll back down and paste it within our attach random crew
-
members array.
-
I misspelled Cineast, so we'll give that a copy and
-
paste it there as well to get that correct.
-
Okay, and then we can provide the number that we want to create into this argument
-
as well, so we'll just have an argument called number, which will be a type number.
-
And provide that into our get random method, so number there.
-
And let's update the name of this to be just IDs.
-
Awesome, so now our attach random crew members method takes in a movie,
-
takes in an array of Cineasts and a number to randomly pluck from the Cineasts.
-
It will get that random number and their IDs from our Cineast array,
-
attach them to our movie via our relationship.
-
And now all that's left to do is make our Cineast title random as well.
-
So let's go ahead and scroll up to the top of our cedar here.
-
And let's do titles as a string array equals an array.
-
And we'll do camera operator as one, maybe an art director,
-
hair and makeup production manager.
-
Might have somebody for wardrobe, a line producer, sound mixer,
-
maybe a cinematographer.
-
I think I spelled that wrong.
-
Okay, I think that's supposed to be an A and a gaffer.
-
And that should be good for our titles.
-
So we'll scroll back down to where we are attaching our random crew members.
-
And for the title, instead of placing in a hard coded string,
-
we will do this get random, provide in our this title.
-
Let's pluralize that name.
-
Scroll back up, plop an S on the end of that.
-
There we go, scroll back down, titles.
-
And we just want one, so we'll provide one there.
-
And then we need the first result, so we'll do zero there.
-
Okay, so now we have our attach random crew members.
-
Let's do the exact same thing for our cast members as well.
-
So we'll give that whole method there a copy and a paste and attach random cast members.
-
The relationship for this will now be cast members.
-
And instead of providing titles, we'll instead want to provide in character names.
-
So instead of creating a manual list of character names,
-
we can actually make use of our Sinisfactory to get a character name randomly.
-
So inside of our reduce call here, let's do const record equals await Sinisfactory.makeStubbed.
-
And this will make us a Cineast using our Sinisfactory,
-
but it won't actually persist it to the database.
-
Now we just have a Cineast record that doesn't exist in the database available to us.
-
And we can do record.fullname to provide the random full name
-
that we got from our Sinisfactory into our character name.
-
However, this is asynchronous.
-
So let's move this outside of this call to simplify things.
-
And let's create many instead.
-
The number that we want to create is the total number of cast members that we're trying to create here.
-
So we'll just pass our number directly in there.
-
This is now records.
-
And now we can do records, reach for the index.fullname instead, and everything will be happy.
-
All right, so now it's time to make use of these two attach calls.
-
So scroll back up, get rid of everything that we have here, just like so.
-
And we can even get rid of these two lines here.
-
Now let's change our game plan here a little bit.
-
So instead of plopping all of our movies into a variable, looping over them individually,
-
let's plop all of our movies into a single variable.
-
So up here at the top, and we'll do let movie records set the type to a movie model array
-
and instantiate the value to an empty array.
-
We'll scroll back down, and we'll just concatenate in each of the results as we create them.
-
So we'll do movie records.concat, wrap that up there.
-
Movie records equals the resulting concatenation.
-
And we'll want to do that for each one of these three here as well.
-
So movie records equals movie records.concat, and wrap those up as well, just like so.
-
And then let's scroll up and do the exact same thing for the ones that we're tapping
-
over as well.
-
So let's do let movie records equals those there, and then we can just get rid of our
-
instantiation up there.
-
Let's get rid of our promises as well, since we have these all housed inside of a single
-
array.
-
We can just do const promises equals movie records.map.
-
We have our individual movie, and then inside of here, we'll await this, attach random cast
-
members, provide in our movie, provide in the pool of Cineasts we have in our array,
-
and then the number that we want to create.
-
Let's do four for right now.
-
Okay.
-
And then we can return this.attach crew members, movie, our cynist pool, and let's create three
-
cast members.
-
All right.
-
Lastly, these two things aren't happy because that's missing parentheses, and then we need
-
to make it async as well.
-
All right.
-
So let's await promise.all our array of promises.
-
Okay.
-
So now we have our array of movie models, which contains the result of each one of the
-
movie factories that we run, including the ones that we tap over as well.
-
We are then awaiting the results of the attach random cast members and attach random crew
-
members for each one of those movies right here.
-
So if we did everything correctly, we should be able to jump back into our terminal.
-
Let's clear that out and let's rerun our migration refresh seed, just like so.
-
Okay.
-
Everything completed successfully.
-
So it appears like everything would be correct.
-
Let's jump into PgAdmin.
-
Let's scroll up.
-
Let's right click on our database, refresh, scroll back down.
-
If we right click now on our crew movies table, view edit data, let's do all rows.
-
Okay.
-
Look at that.
-
We got 1260 rows back.
Join The Discussion! (0 Comments)
Please sign in or sign up for free to join in on the dicussion.
Be the first to Comment!