🕰️ Chapters
- Adding the Delete Form and Button
- Defining our MoviesController Destroy Handler
- Considering Relationships when Deleting
- How To Delete Relationships when the Delete Does NOT Cascade
- Testing Out our Deletion
Transcript
-
(upbeat music) So at this point within our admin dashboard, we can create movies, edit them,
-
add, remove cast and crew members, but we cannot delete them. So that's the last thing here that we need to take care of. Let's go ahead and add a little delete button right down here that will allow us
-
to delete a movie when clicked. So let's hide our browser back away. For this, we're gonna want to jump into our pages admin movies index page,
-
and we'll add this into our actions TD, which is the last TD in the table for each row. We can add this underneath our edit
-
and we'll add it in as a form method, post action equals route admin movies.
-
And the route name here should be destroy. We need to pass in the ID as the route parameter, which would be our movie.id.
-
And we need to signal this as a delete HTTP operation. So we can add in a third argument with QS
-
and an underscore method to use HTTP spoofing to assign this as delete. All right, go ahead and add in a couple of spaces there
-
and end that element. I'm gonna go ahead and break those down on the separate lines as our action URL generation there is a little long. All right, so within this form,
-
let's add in a button type, submit and class. We want to be text read, maybe 500,
-
so that it's noted that this is a dangerous operation and we can give the text for that as delete. This route should already exist, but we can go ahead and double check that.
-
I believe we did assign that as a resource. So we'll hit command P, type in routes and jump into our start routes file. Believe our admin section is all the way down at the bottom.
-
So we'll scroll on down here. And sure enough, there is our router resource movies with our admin movies controller as a handler. So the route is defined there.
-
We can jump into our admin movies controller. And if we scroll on down, we created this controller as a resource. So we should already have a destroy method right here.
-
So cool. We have the params, but we're also going to want the response so that we can return and redirect right back. And the first thing that we're gonna wanna do
-
is query the movie so that we can grab an instance of it. So const movie equals await movie.findOrFailParams.id.
-
To actually delete this movie out, we can do await movie.delete, which will delete it out of the database.
-
And then we can return response, redirect right on back to the admin movies index page. Cool. So in terms of our movie delete,
-
what is this going to do? Well, it's going to delete that record out of the database, as mentioned earlier. If we come over here and we jump into our movie model, so right here,
-
and we scroll up to the top and let's run through what we have. So we have a status ID, writer ID, and director ID.
-
These relationships are all belongs to relationships. They belong to the movie record. So whenever we delete the movie record out of the database,
-
those relationships will automatically be deleted as well, as they were strictly housed on that record itself for the movie. In terms of our other relationships,
-
which if we keep scrolling down here are for our watch lists as well as our crew and cast members, those are not automatically deleted
-
unless we explicitly told them to delete on Cascade within our migration. Remember we covered that earlier. So let's go through and see which of these relationships
-
we applied that to. So let's go into our database. We have our watch list, crew members, and cast members relationships that we're looking at here. So let's dive into the migrations. I'm going to expand this out
-
so that we can see the full names and we can scroll down a little bit to see them all. These are our crew and cast member pivot tables. So if we go into here and we take a look at the integer
-
in charge of the relationship on this pivot table, you can see this on delete Cascade. So whenever we delete out the movie, this pivot table record should be automatically deleted
-
because we've told it to delete on Cascade with the relationship itself. So for our crew movies, the deletion should happen automatically for that relationship.
-
So we shouldn't need to worry about it. If we take a look at our cast movies, this has the exact same thing going on. So for our movie ID, it's got on delete Cascade,
-
which when we delete out the movie, the deletion will cascade through for any pivot table records matching that movie's ID. So those will automatically be deleted there as well.
-
As for our watch list table, it looks like we have the on delete Cascade here as well for our movies. So we don't need to worry about it there either, but what if we did?
-
So let's say for example, we needed to worry about deleting our watch lists in addition to our movie. Let's say that we didn't have that on Cascade delete there. So it didn't happen automatically.
-
What we would want to do is also query the watch lists. So const watch lists equals movie, and we can reach through the relationship. So related watch list.
-
At this point, we don't care about the user because the movie would no longer exist. So we need to automatically remove it regardless of the user. So we can just do query to grab all of them.
-
With each of those watch lists, we would then need to delete them before we actually delete the movie. Otherwise we're gonna get a foreign key constraint error as there is a foreign key between the watch list and the movie,
-
making sure that the movie exists for the watch list record. So before the movie deletion, we would need to, with the way that we've queried them here, loop through and delete them.
-
So we could do for let watch list of watch lists, and then do await watch list dot delete. Nope, that's a promise.
-
We need to also await the query results there. Okay. Which will loop over each watch list that we have individually one by one, deleting it out.
-
Which would not be the most performant approach to this particular deletion. Instead, what we'd probably want to do is use the actual query builder to delete it out altogether.
-
So we don't need to query the watch list at all, but instead we could do query dot, and there is a delete method that will delete any matched watch lists that we've queried here
-
out of the database automatically for us. And then once we have those watch lists deleted, we're a-okay to then remove the movie as any potential foreign key matches
-
have now been removed from the watch list. Again, we have on delete cascade for all of these relationships. So we don't need to worry about this at all.
-
The deletion will happen on cascade automatically for us whenever we delete out the actual movie record. So we can omit that altogether, and we should be able to just leave things
-
how we have it right here. And we shouldn't need to manually delete those as many and many to many relationships that our movies have. So with that applied, let's go ahead and jump back into our browser and give this a go.
-
So we have our new delete button right down here. Let's try to delete awesome movie number three, which should also remove the writer as that's a belongs to.
-
Our director, that's also a belongs to. Our cast members and our crew members, which are both many to many relationships. And if applicable, any watch lists
-
that this movie is a part of. So if we hit delete there, we get redirected right on back, and we still see the movie. We jump into our terminal,
-
invalid or expired CSRF token. Forgot to add that into our form. So let's jump back into our text editor here. Let's go back into our index page. We have our form right here.
-
Within that form, we need to apply our CSRF field. Forgot about that. Let's add that in now. We just saw our browser refresh there in the background.
-
So now we should be good to go ahead and try to hit delete once more. And there we go. Our movie is now gone. It no longer exists. It's not in this table at all.
-
And any relationships for it have been automatically cascade deleted for us. Let's do a couple more just to test it out. So let's delete my cool movie two, my cool movie one, as well as some of the movies
-
that we created with our Cedar. So I'm your boogeyman, that's gone. Me and Miss Jones, that's gone. Smooth, gone. So awesome. Everything seems to be deleting A-okay.
-
And we now have the full administrative crud flow for our movies completed.
Allowing Admins to Delete Movies and their Relationships
We'll learn how we can safely delete movies and their relationships. We'll discuss how we need to consider foreign key constraints, and what to do when our deletes aren't set to cascade.
Join the Discussion 2 comments
-
-
Responding to iphonegeek-me
Hi iphonegeek-me!
Method spoofing with
_method
is documented on the request page. I also introduce it in this series in our HTTP Method Spoofing HTML Forms lesson.0
-