Handling PATCH Updates0:00
In the previous episode, we implemented the replace methods on the TicketController and the AuthorTicketsController, and that handles the PUT requests. Now we need to handle the PATCH requests by implementing the update method. Now handling a PATCH request is a little bit more involved, because a PUT request is very easy. We're taking all of the data, and all of the data is supposed to be involved with a PUT request. We update all of the attributes, and we're done. With a PATCH request, we might have one attribute, we might have two attributes, but we aren't going to have all of them.
With a patch request, we might have one attribute, we might have two attributes, but we aren't going to have all of them. Well, I guess we could, but if you're going to replace all of the attributes, you might as well use a PUT. So in this case, we are going to have to check to see what was provided in the request, and then only update those attributes. So things can get very messy very quickly, but we're going to try to keep things as clean as possible. Now, I just implemented the routes for the patch requests. Now we just need to implement the code.
Now, I just implemented the routes for the PATCH requests. Now we just need to implement the code. So let's start by taking the code from the replace method, because that's going to give us everything that we would think we would need. But let's take a look at this. So this is grabbing all of the input data, the title, description, status, and the authorID, building this model array so that we can update that model. And that's great for PUTs, not for a PATCH, because we need to check, well, do we have title? If we do, then we need to update that.
title? If we do, then we need to update that. Do we have description? No. Then we don't need to update that. And there's a lot of if statements, or at least a lot of checking involved, and I definitely don't want to do that here inside of the controller. And really, I don't even like what we did for the replace method and for the store methods where we built that model array. Instead, I would like to have maybe one line of code here.
Designing mappedAttributes Helper2:01
where we built that model array. Instead, I would like to have maybe one line of code here. And that's something that we can easily do, actually, because we could use our request to have, let's say that we'll have a method called mappedAttributes. And we'll say that the job of this mappedAttributes method is to take the inputData, check to see if that inputData is there, and then build an array that contains only the attributes that we need to update. That's going to work perfectly for a PATCH request. It's going to work perfectly for a PUT request, and even for a POST request, because in those cases all of the attributes are required.
It's going to work perfectly for a PUT request, and even for a POST request, because in those cases all of the attributes are required. So this is going to be great. So our code is going to look like this, basically, so that instead of creating that array, it's going to be done behind the scenes inside of our request. So that all we have to do is pass that mapped attributes to the update method, and we're done. So we could do that for the replace method, and we could do that for creating that model. So let's go to the store method. Let's get rid of that model array, so that then all we need to do is just implement this
Creating BaseTicketRequest3:04
So let's go to the store method. Let's get rid of that model array, so that then all we need to do is just implement this method. Now, because we are going to be using this in, well, every ticket request, it kind of makes sense to create a base class for all of our ticket requests. So let's start with our ReplaceTicketRequest. Let's just copy that. We will rename the copy to BaseTicketRequest, and we, of course, need to change the name of that class. But here we can just specify the things that we will need for our base ticket.
of that class. But here we can just specify the things that we will need for our base Ticket. For example, we don't need to really specify the authorize, because that will be handled in the child classes. And really the same thing for the rules, so we can get rid of the rules. But the messages method, we would need inside of the StoreTicketRequest, the UpdateTicketRequest, and the ReplaceTicketRequest, because we need to validate and provide our custom message for the status. So that's going to be great. We can get rid of messages here inside of ReplaceTicketRequest.
So that's going to be great. We can get rid of messages here inside of replaceTicketRequest. Let's open up the StoreTicketRequest, and we will get rid of messages there. We do need to inherit that BaseTicketRequest, but that's going to be easy enough to do. So let's be sure to do that in all three requests. And here for update, since we haven't done anything with this, we need to authorize that to true. Our rules here is going to be very similar to replace. In fact, we could just grab that code and paste that inside of our rules. The only change that we need to make, though, is instead of required, this is sometimes
In fact, we could just grab that code and paste that inside of our rules. The only change that we need to make, though, is instead of required, this is sometimes required. So we'll make that change, and our rules are going to be fine. And that's practically it here. So we can close all of these files so that we can focus on our base ticket. So we want this method called mappedAttributes. So let's define that. And the first thing that we need to do is build a map between the input keys, which are in line with data.attributes.status.
Building Attribute Mapping5:01
And the first thing that we need to do is build a map between the input keys, which are in line with data.attributes.status. I'm just going to refer to those as data attributes. Let's open up at least one of these so that we can copy and paste here. But our attribute map is going to look like this, where the key is our data attributes, and then the value is going to be the attribute on the model. So there's the title, there's the description, there's the status, and then we also want the author_id. But I guess we should also go ahead and include the created_at and updated_at attributes as well.
But I guess we should also go ahead and include the createdAt and updatedAt attributes as well. So we will have those and then updatedAt. So this is our map. We're just taking what is provided as a key from the request and mapping that as the attribute name as the value. So with that in place, then we need to build an array that contains the attributes that we want to update. So that then we will iterate over our attribute map, we will see if the request contains the key so that we can get its value and add that to our attributes to update.
So that then we will iterate over our attributeMap, we will see if the request contains the key so that we can get its value and add that to our attributes to update. So we'll have a foreach attributeMap as, and we'll break this down into key and then attribute. And we will check if the request has the input key, then we will add the model attribute to our attributes to update and we'll set its value to whatever value was provided for the input key. And that's going to be it. So that then we can just return attributes to update and we're going to go there. That should work.
Testing PATCH in Postman6:41
So that then we can just return attributes to update and we're going to go there. That should work. I don't think that there's any other thing that I missed, but we will definitely find out. Let's go to Postman. Let's copy the PUT request for our ticket and we will just need to make a few changes here. Of course, we need to change this to PATCH and the name will be patchTicket. And this already has a body here, but we only want to specify one or two of these values so that we can see if it's actually going to update things.
And this already has a body here, but we only want to specify one or two of these values so that we can see if it's actually going to update things. So this was ticket with an ID of 101. Let's make sure that we have that fresh data. Okay, so the title was changed to changed title two, then description. So I tell you what, let's change the title. Let's change the status. And if that works, we'll just call that done and then we will move on. So for our PATCH request, we will get rid of everything else because, well, we are patching this.
So for our patch request, we will get rid of everything else because, well, we are patching this. We aren't replacing everything. So the title we'll say is changed title three and we'll leave the description alone, but we will change the status to C for completed. And let's send that request. It looks like, yes, our title changed, our status changed. Let's make sure and let's make a get request for that resource. Sure enough, that data has been updated. So perfect.
Updating AuthorTicketsController8:01
Sure enough, that data has been updated. So perfect. That works just fine. Now we need to implement this functionality inside of our AuthorTicketsController. So let's do that and let's just copy the replace method because that's basically everything that we need to do except that we of course need to change the name to update. The request needs to be UpdateTicketRequest. We will still have the authorId and the ticketId. We still need to get that ticket or at least try to get the ticket. We need to make sure that the ticket's userId is the provided authorId, but then we'll
We still need to get that ticket or at least try to get the ticket. We need to make sure that the ticket's user_id is the provided author_id, but then we'll get rid of this code because we will use the request mapped attributes method. So that's going to work just fine there. Then we can use this method inside of our others. So for our replace, we will get rid of that model and we will use our request mapped attributes. And let's go to the store method here. Since all of this worked for our normal TicketsController, I'm just going to assume that it's going to work here. But you know what they say about assumption.
it's going to work here. But you know what they say about assumption. So I guess we better test this. So let's go to our UsersController and let's duplicate the putUser ticket. This is going to be the patchUser ticket. And before we do anything else, let's make a GET request for this. So we will get all of the tickets for the authorId of 1 and the id of 20 for that ticket is the first one. So we can see that the PUT request works. We will change that to PATCH request works.
So we can see that the put request works. We will change that to patch request works. I will set the status to on hold. So let's go to our patch request. Let's change the type of request to patch. And then for the body, once again, we don't need all of these things, but we will change the title to patch request. Let's change the description to implement the update method. And let's leave the status alone. So we should be able to send that request.
And let's leave the status alone. So we should be able to send that request. We get a response. We can see that that ticket was updated. So everything is working just fine. We now have the ability to completely update a resource, both with a PUT request and a PATCH request. And so in the next episode, we will start working with token abilities so that we can control what users can and cannot do.
control what users can and cannot do.
