Update flow test tweaks0:07
All welcome back. So we're working on updating an idea, and the cliffhanger in the last episode was deciding should we try to reuse our existing action class? Or do we instead create a second action class for updating an idea? Let's figure it out. So here's the test that we currently have to verify that everything's working the way we expect. So if I give it a run, but actually real quick, uh,
that everything's working the way we expect. So if I give it a run, but actually real quick, uh, we change the label to update rather than create. And then when you're done, I really expect, think about it. You, you edit the idea, you fill out the model, you submit it, you should probably be redirected back to that same idea page. So why don't we say assert routes should be, um, idea show. Yeah, I think, I think that's right, but clearly it's not.
um, idea show. Yeah, I think, I think that's right, but clearly it's not. Maybe we passed this through as an array. Yeah. Okay. Let's give it a run. It's a lot to remember. Okay, so of course it's failing because we aren't yet updating the idea, but that's okay. This is telling us what the next step is. Perfect. So I'm gonna return to our idea controller to the update action. And yet this point, it's not working
Create update action class1:14
to the update action. And yet this point, it's not working 'cause we're literally not doing anything. Okay? So here's what I wanna do to start in our store action. We have this create idea action. And we don't know yet if we can just tweak this a little bit into create or update idea, right? And I don't know yet. I, I genuinely don't know. So what I'm gonna do and duplicate this, I'm gonna add a,
And I don't know yet. I, I genuinely don't know. So what I'm gonna do and duplicate this, I'm gonna add a, um, a second one for update idea. And then when we're done, we'll just compare notes and decide are these similar enough that we can merge them or are they unique enough that it, it's just cleaner and more, it provides more clarity if we split them up. So we'll have an update idea, action. Okay, let's get going. So update idea. And before I even get started, we know that we don't need
So update idea. And before I even get started, we know that we don't need to pass the user, right? Because the user is implied based upon the idea that we're updating, right? So I can get rid of that entirely. And then if I go back to idea controller, down to update, I'm going to ask for, um, update idea. Okay? So I could say action handle. And I need to know what is the idea we're updating.
Okay? So I could say action handle. And I need to know what is the idea we're updating. We're gonna pass it through right here. Now what about the attributes? I need the attributes. All right, so let's see how we did it in store and we passed through the safe request data. So we'll do the same thing. So do we want the attributes first or the idea first? And again, these are things you need to stop and think about.
And again, these are things you need to stop and think about. How do I want this to work? Update, idea, handle. And do I provide the attributes and the idea model? Or do we or do we reverse it? Why don't we keep it like this? I think, okay, so we're gonna have attributes, we're going to have the corresponding idea that we're updating. Once again, we prepare an array of only the data that's acceptable here.
Once again, we prepare an array of only the data that's acceptable here. Um, we determine if we have an image, okay? And also by the way, we should, we should check if the image is an instance of uploaded file. Uh, there's some little things we can, we can tweak there. Uh, but then we no longer do this. We would say idea update and we would send through the data. We'll need access to the idea itself.
Syncing steps on update3:26
We would say idea update and we would send through the data. We'll need access to the idea itself. Alright, so next the syncing of the steps. This is actually a little bit tricky if you think about it because when we were creating an idea, all we had to do is call create many. But now we're potentially deleting some from the database. We're potentially updating. We're potentially, um, adding new records. For example, if I were to hit edit idea, yeah,
We're potentially, um, adding new records. For example, if I were to hit edit idea, yeah, imagine we get rid of record videos, but we add some new ones. Maybe we tweak publish course. That all has to be synchronized. So I think we could use Upsert for that. But here's another, maybe a simpler option that will get us there a little bit quickly, uh, a little bit more quickly.
Restructure steps form data4:09
that will get us there a little bit quickly, uh, a little bit more quickly. I'm gonna return to our modal and let's go to our actionable steps. Here it is. Yeah. So currently we're just passing through the description, but why don't we do this instead? Let's just make this form the source of truth for whatever steps we should have. So we'll have one for description,
for whatever steps we should have. So we'll have one for description, and then I will also have a hidden input for the completed status. All right, so now each step will be an object rather than a string. So for example, I would bind to step description and step completed. Although in this case, I think completed we'd bind a Boolean and I think we just want the string.
Although in this case, I think completed we'd bind a Boolean and I think we just want the string. We might have to do that. I'll double check that. Uh, but nonetheless, yeah, that's what I'd like to do. So now if I want these to be grouped, we would need, um, a, a proper index. So for example, here's maybe something we could do. Let's just bind it so that I can reference the index variable. I can say this will be index. All right?
that I can reference the index variable. I can say this will be index. All right? And then we'll do the exact same thing here. Cool. Alright. So now for each uh, step we will submit to the server, uh, basically an object that contains the description of the step as well as whether or not it is completed. Okay? So now we just have to scroll up and update our steps array, uh, of, before it was just an array of descriptions, right?
and update our steps array, uh, of, before it was just an array of descriptions, right? But now we're gonna change it and it's gonna be an array of objects basically. So we'll say for each step, I only care about the id, the description and the completed. And that's what we will, that's what we'll use to create those bindings. So let's go to idea controller and into idea request. And if I scroll down, yeah, now steps will not be an array
So let's go to idea controller and into idea request. And if I scroll down, yeah, now steps will not be an array of strings, it's gonna be an array of objects. And we'll have one for description that is a string and then another one for completed. That will be a Boolean. Yeah, like that. So now let's just di dump the request validated data and see if this works. 'cause we did a lot there. I might have made a mistake. Let's edit the idea. And let's see. Add a new one here.
'cause we did a lot there. I might have made a mistake. Let's edit the idea. And let's see. Add a new one here. Maybe. Oh, already we see an issue here. Okay, let's fix that real quick. I think I have an idea what that is. Let's go to our modal and go down to our steps. All right. And by the way, this is probably the most confusing, difficult portion of the entire course because we're dealing with a lot of JavaScript stuff. Uh, that may not be as relevant to the larva learning,
because we're dealing with a lot of JavaScript stuff. Uh, that may not be as relevant to the larva learning, but it's just how it goes. Building a, an app. So in this case, yeah, I can see right here the key should be the idea of the step. That's the unique part. And then also we gotta remember when we uh, add a new step when the user types in a new step. Well this needs to change, right? So here's what we can do. I can say steps. Do push an object.
Well this needs to change, right? So here's what we can do. I can say steps. Do push an object. Now where the description is that and the completed status is false. And then this, uh, don't forget though, you can also delegate to a function like add step and that can be responsible for it. I'm just doing it in line 'cause it's simple here. So hopefully let's cross our fingers. A lot of moving pieces here. But let's see if it works.
So hopefully let's cross our fingers. A lot of moving pieces here. But let's see if it works. Record videos, add a new one. Okay, that part works. And now hopefully this gets submitted to the server properly steps. And there we go. So we have description, but we don't have the completed portion, so let's figure that out and then we should be on our way. Yep, there it is. We forgot to do the binding.
and then we should be on our way. Yep, there it is. We forgot to do the binding. Okay, so I already know that's gonna work. So let's do this. Let's go up to idea or idea controller. Let's clear that out. We delegate to the action. The action, um, handles the image, it handles updating the idea and now it's gonna synchronize the steps. So yeah, if we wanna think of the form as the source of truth, then I would do this.
So yeah, if we wanna think of the form as the source of truth, then I would do this. Idea steps, delete, just clear out that table and we will rebuild it. And then I can say idea steps, create mini and pass through the steps or none. Yeah, I mean I think, I think that would do it. Alright, so let's take a look at this. Here's what updating an idea is. We grab the attributes we care about.
Here's what updating an idea is. We grab the attributes we care about. We potentially upload an image. And by the way, we should, we should delete an existing image if it doesn't match. And let's file that one, um, for an update. Next, within a transaction, we update the idea, we clear out the steps and then we rebuild, uh, with the new steps that are provided.
and then we rebuild, uh, with the new steps that are provided. Finally, an idea controller. When we are done, let's redirect back. So return a redirect. Um, yeah, we could go to edit. Let's just go return back and we'll say, uh, success idea, updated. All right, so let's test it manually and then let's test it. Um, programmatically edit the idea. Come down here, record videos, do a thing,
Um, programmatically edit the idea. Come down here, record videos, do a thing, update this, submit it. And I think we're in business and we are do a thing. So notice if I have published course here though, uh, that's now activated. If I scroll down, if I add another one here, I get rid of do a thing. Well, ideally we should now have two. But published course should still be, um, completed.
Well, ideally we should now have two. But published course should still be, um, completed. And yet that's just one way to do it. Another option would be to do a a slightly more intricate upsert where we specify how to update um, the steps table and what to do if there already is a matching record there. I think though, like this ends up being just a little bit easier though, just wipe it clean and rebuild it. So now I'm gonna switch to full screen
Decide to keep actions separate10:04
easier though, just wipe it clean and rebuild it. So now I'm gonna switch to full screen and let's look at these side by side. And we're just gonna compare notes and figure out is it possible that these could be merged? It's pretty simple, but what we would end up having to do is just a lot of checks of like, do we have an idea? Then do this else. So we'd have more than one if else statement. And in situations like this, it might just be easier
So we'd have more than one if else statement. And in situations like this, it might just be easier to keep them separate. So with that in mind, that's what we're gonna do. Alright, let's go into idea test and let's give it a run. And oh, it fails, but I know why. Okay, so here it's saying, okay, well you expected this, but actually there was an existing link. And that's because when we built up a factory for Idea, idea Factory, it gives us one link.
Fix failing tests and debug10:50
And that's because when we built up a factory for Idea, idea Factory, it gives us one link. So we started with an existing link. So here's what I'm gonna do. Let's, um, just clear this out to simplify a little bit. All right, so we're gonna open the form, fill out a title, uh, fill out a status, fill out a description, add a link, and then add a step. So now that should give us a link that includes lar cast.com, but also the existing link that was there.
So now that should give us a link that includes lar cast.com, but also the existing link that was there. So idea links and give me the first one there and then we should have one step. Okay? And it passes. Okay, very good. So now let's just make sure that creating an idea works. There might be one issue because we changed the structure. Yes. Okay, let's fix that real quick. I think I already know what that is. So now, yeah, so when we add steps,
I think I already know what that is. So now, yeah, so when we add steps, we have a full object there, which means I can just say attributes, steps, or an empty array, right? Because it's already formatted with a description and a title. Or we could map over that and be explicit that we're expecting a title and a description here or a description and a completed status here.
and a description here or a description and a completed status here. So I think that will do it. Maybe let's give it a shot. No, it's still fail. Oh, but we changed the error. So failed asserting that actual size one match is expected. Size two. All right, so I'll show you how I would debug this. I'd go to my store action and I just wanna see so often it's what you expect was passed to the server is not.
and I just wanna see so often it's what you expect was passed to the server is not. So if I die and dump the validated attributes, yes. So notice I expected two steps here, but we're only getting one. And my guess is we're overriding something. So you'll remember right here we added a step and then we added another step, but the other one was not working for some reason. Okay? So I would bet the id the issue is the
but the other one was not working for some reason. Okay? So I would bet the id the issue is the index or the id. 'cause we assume this is it. We would assume there's an id. Uh, but when we're adding a new one, we don't have an id. So I wonder, can I get away with just doing the index? 'cause I'm not re I could be reordering. What would be a good way to do this? We could generate an id. We could just default to an index. If there is none, that's not quite right either,
We could generate an id. We could just default to an index. If there is none, that's not quite right either, but let's just see if that fixes it. But I bet it does. Yes. So now notice we do get both. Okay? So we could just generate an id. Okay, so back to id, ID controller. If we run it now we get green. Okay, so we have some passing tests. So now just to wrap up in terms of organization on browser, I'd probably add a new folder for idea.
Refactor and expand tests13:34
So now just to wrap up in terms of organization on browser, I'd probably add a new folder for idea. I would kind of match that. I would move this in and then I would separate these. So I would rename this one to once again create idea test. I would duplicate it and then I'd have another one. Update idea test. All right, so create idea test can be a little more simple. And this is especially useful, it's in situations where you're doing more than just one test.
And this is especially useful, it's in situations where you're doing more than just one test. So I'll show you, if we get rid of this, now we have one for it, an existing, um, an existing idea. Next though, maybe it defaults to, um, the original values, right? It shows validation or old values. So there's all these different tests that you could write in real life. So I'll show you, like we could say right here,
that you could write in real life. So I'll show you, like we could say right here, it shows the initial title, you know, stuff like this. And you could say, all right, well let's sign in and create an idea. And if I visit, um, the show page and open the modal, then I would expect an input to be filled, right? So as it turns out, there's an assert value method we can use, uh, for this exact use case.
So as it turns out, there's an assert value method we can use, uh, for this exact use case. You give it the selector, in this case the input with the name of title, and then the value that that input should have, in this case the title from the db. So this should almost certainly pass and it does. Okay, so now, yeah, I'm not gonna do all of this, but you could say it shows the initial state input state and then just update these. So like the description should be equal to that
and then just update these. So like the description should be equal to that and it should work green. Uh, maybe one more. The status should be equal to the ideas status value, because it's an enum. Give it a run. And yeah, rinse and repeat. These are the sorts of things you will be writing, especially for your important forms. Make sure validation is in effect. Uh, make sure initial values are set.
Make sure validation is in effect. Uh, make sure initial values are set. Uh, make sure redirects are handled. Make sure your image is synced properly. Make sure these steps are synchronized and it really does give you the assurance, by the way, to refactor your code when you need to. So if you wanna tweak how we update an idea, you can safely do that with the assurance that if you mess something up, your tests are gonna fail
you can safely do that with the assurance that if you mess something up, your tests are gonna fail and prove to you that you need to tweak a couple things. Okay? Alright. So yeah, I, I would say this episode probably specifically may be the most difficult one just due to the fact that we're writing a bunch of alpine code that you may not be familiar with. Uh, but that's okay, you made it through. So in the next episode, let's move on
Uh, but that's okay, you made it through. So in the next episode, let's move on to the edit profile section.
