Lesson Description

The "Deleting Workouts" Lesson is part of the full, Complete Go for Professional Developers course featured in this preview video. Here's what you'd learn in this lesson:

Melkey finishes the CRUD functionality by adding the ability to delete workouts. The delete workout handler ensures the workout exists and returns an empty payload after deleting the workout.

Preview
Close

Transcript from the "Deleting Workouts" Lesson

[00:00:00]
>> Melkey: So, if we look at a PSQL now, we can validate this. So, before we saw the two previous entries, if we do this, now we see deadlifts, pull-up, plank with the modification that we see. We have the workout id all tying back into the workout that we have, again, one too many relationship.

[00:00:15]
So, I think it's fair to say that we are able to successfully update a workout, we're also able to create a workout, we can check the workout as well if they exist. So back here, whatever you use, you can just simply do curl http://localhost8080/workouts/1.
>> Melkey: There you go.

[00:00:58]
So we can retrieve, we can create, we can update, it's looking pretty good. The few things that are blatantly obvious that we're gonna improve, and before we get to those, we need to add the last kind of Horseman of crud, which is delete. And that shouldn't take us too long, but I do believe that now that kind of the way to do it is fairly obvious, right?

[00:01:22]
We start with a database layer, create it there, hook it up to the API workout handler, and then we route it. And we can repeat this for any kind of path we want, right? Any path that is specifically going to be interacting with the database. If there's no interaction with the database, you can skip the database layer altogether.

[00:01:40]
But since we're not gonna do that, let's go back to the workoutstore.go, and question to anyone, what is the first thing we actually need to update here?
>> Speaker 2: Interface?
>> Melkey: Yes, exactly, we need to update the interface. Cuz if we don't, we're gonna get an error saying that we cannot pass the workout store as something in our workout handler.

[00:02:01]
So here in update workout, we're gonna create a new method called DeleteWorkout. DeleteWorkout is gonna take one argument, which can be id of type int64 and it's gonna respond with an error, all right? So now let's go all the way down, make some room for yourself and in here we should probably know the drill by now.

[00:02:20]
Let's go ahead and make our func, it's gonna be (pg *PostgresWorkoutStore). Let's call this DeleteWorkout, give it that argument, int id 64, make sure it responds with the error like so.
>> Melkey: Let's make that query, it's gonna be pretty easy. Delete from workouts, where id equals the first value we are going to pass in and the only value we're going to pass in.

[00:02:50]
>> Melkey: Following the same kind of blueprint we laid out, we can just do result, and error is gonna be pg.db, we can execute that query, pass in that query, and the one argument which is id.
>> Melkey: And then everyone's favorite checking for error. So if error does not equal to nil, we first check if it's nil or not, we can then return whatever that error is, okay?

[00:03:14]
You don't need to necessarily do this, but I'm going to again, just to be explicit. We can do rowsAffected as result.RowsAffected, check the error here. So, if error also does not equal to nil, maybe we can return nil. Otherwise, if rows affected is 0, we can return sql.ErrNoRows like so, everything works correctly, we can just return nil.

[00:03:47]
>> Speaker 3: Does that need to be flipped again? If you have error not equal to nil, and then actually, never mind.
>> Melkey: Let's read out, so we first check if it's not nails. It's not that it has to be flipped, this has to be error.
>> Speaker 4: You ever set up some sort of hockey or shortcut to do if error does not equal.

[00:04:12]
>> Melkey: No.
>> Speaker 4: You typing it?
>> Melkey: I'm a masochist, I love typing it at this point. There's been attempts to add packages that do it for you, doing all these things, that's just been rejected by the Go community, like outright rejected. Very nice, so now proud to announce we have all of the functions for crud in our workout store, creating, reading, updating, and deleting.

[00:04:37]
And we should know that now we can go head on, back up to a workout handler like so. Let's go all the way down, give us some room, and here we just need to create that delete function. And I actually am gonna challenge everyone here, I'm gonna type it out, see if you can do it yourself.

[00:04:58]
If you can't, that's not a big deal at all, we can make this a mini exercise. I just don't wanna pause in the action and then kinda continue, so feel free to just look and copy what I write or try it out yourself. Maybe the way you do it will be cleaner and better, right?

[00:05:11]
So, let's do this together, I won't be talking too much,
>> Melkey: And you don't have to worry about the naming is just the only part is if you do name it something different than handle, delete, workup by id, like the one I have here. When you add it back to your routes, make sure reflects the function name, whatever you choose to use.

[00:05:41]
>> Melkey: Okay.
>> Melkey: I'm gonna go ahead and grab this.
>> Melkey: I'm gonna pull that worker id, cuz we need it. And then here can do something like this, the workoutStore and the DeleteWorkout method and actually pass in that workoutID
>> Melkey: All right, so I check if that error is going to be a sql.ErrNoRows.

[00:07:06]
>> Melkey: Okay, then we check with the error exists or not, and then here we can just simply do w.WriteHeader, cuz we don't want to respond with any. You can add a particular message if you want in your JSON, if you want to do successful, delete it or not, feel free to do that.

[00:07:19]
I'm gonna do (http.StatusNoContent).
>> Melkey: Like so. So let's go back to the route, we can check if your function works, again, hopefully you try to maybe do something yourself. If you just felt you wanted to copy and learn it, totally fine, right? Whatever is easy for you, so here we can do workout and then pass in that slug id.

[00:07:46]
And in here we'll pass in app.workoutHandler and then handle, delete, get workout by ID as a first-class citizen. All right, moment of truth, let's bring down the server and go run main.go, okay? And here in this particular manual test, we wanna test for two things, well, three. One, does it work, two, is it deleting the thing it should be deleting, and three, is it deleting the workout entries as well, all right?

[00:08:15]
So, if we look back in our psql, we have one workout, right? We just have the workout id, belongs to 1, so the slug that we're gonna pass into our curl should be /1. You can do curl -X DELETE, which is the method, the HTTP method, localhost8080/workouts/1,okay? And if you do -v verbose, it will give you the HTTP status in mind, I'm not responding with any JSON.

[00:08:44]
So, there's no true indicator if it was deleted or not, you can modify that. I use an HP header or status called stud. If you run this, like so, and then if we go back and run the exact same query, select all from worker entries, it should be empty.

[00:09:01]
And if we do select all from workouts, it's empty as well. So, we have now fully gone through the implementation of a CRUD app, we are able to create, read, update, and delete, and I think that's pretty cool.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now