Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Lessons:14Length:2.4 hours
  • Overview
  • Transcript

2.9 AJAX Remote Calls

In this lesson, you’ll learn how to use JavaScript in the context of a Rails app. To demonstrate, we’ll use JavaScript to enable a more dynamic experience when marking tasks as done.

Related Links

2.9 AJAX Remote Calls

In this lesson, we'll focus our attention on building a little extra feature. It's not really a major one, but it will definitely improve the flow of using our application. Consider the example where we are searching for a particular project. We have a list of tasks, and for each one of them we want to check them, mark them as done. Instead of going to the task and choosing Edit and then marking them as done, we want to do this just by clicking on this check box into these tasks. How can we accomplish such a feature? Well, you might be thinking of using Ajax for the purpose. That's exactly what we're going to do. So the objective is when we click on this check box it will communicate with the server, mark that task as done and after that we can consider sending an email to whoever participated in that specific task. So basically when you click on the task, everyone that posted a comment Has an email address and we'll be sending that email to those people. So let's begin with the Ruby part, we're gonna need a route that will actually toggle the state of our task, and for that purpose we're going to create a new route. Let's go to config/routes, and let me just take the chance and teach you about this root method. This root method basically defines what controller and action should be rendered as the home page. So, by changing this, for example, to projects#index, this will have a significant impact in the way that when we go and choose the homepage so, localhost:3000/ without anything else. We will go straight to the list of projects. So, let's go back to where we were and choose the first project which has one task. Okay, now, let's add that specific method we want. I'm going to utilize the following instruction. member and then passing a block, which in turn gets this patch method. So patch method called Toggle. This will allow us to have something like this, #/tasks/1/toggle. This is the URL that's going to be generated. And the name for this route is actually called Toggle Task Path. So it takes on the names that are part of the URL and creates a new method based on that. It will return this very address. What this means is we're going to pick up on one single task, hence the member instruction. Because if you wanted to have something like a different list of tasks, say, for example, /tasks/latest, or popular, something like that. Instead of using the member block you would use the collection block, so everything that goes inside the collection block affects the recourses, not a single one, but the collection. In the member block you will consider a single task, so if we type in something like rake routes in the console, you will see the following output. Toggle task is the name, so the prefix for the route, it is the PATCH method, and this is the URI pattern, so we will have /tasks, the ID, then the toggle. The controller action we should have is called toggle, just like the name of the route. So let's go there which is our next step to go to the controllers. Choose the TasksController and I guess I am just going to go to the very end and edit the toggle method. The toggle method will have the following code. Our objective is to find the task. So actually what we need to do is use this before action filter, it's already there, we just need to use toggle. There you go. And now let's go back to where we were. We will have this task model already found. So from here we'll use the toggle method. It's actually there, so we can use it. It only works with booleans, though, so don't forget that. Since done is a boolean, we just toggle it. This method returns the very same task object, so we can immediately call save on it. This will toggle the done attribute, but just in the object. We then need to persist it. At the end we just pass a header with a status code. The status code that I want is 204 which represents no content, but still the result is successful. Anything in the range of 200 is an okay request. But since we don't want to do anything with it, we just render nothing at all. We just print out this status code. As far as Ruby goes, I believe this is it. Now the last thing that we need is to improve the view in order to have some sort of a JavaScript feature. Let's go to views, projects, and then show. As you can see, this is the list that we have for all of our tasks. Each one of them already has an ID, but in this specific scenario I want to add a class. The check box will have a class so that we can identify it. I'm gonna call it task, or even task done or something. This will properly group each one of the specific check boxes and then when each one of them is clicked, we're gonna perform an Ajax request, and when it's done, we'll be able to do something about it. For example, create a little highlight of some sort. So let's see if this is working. Let's go ahead and reload this page, and it seems we didn't break anything which is really good. The next step is to actually trigger this event and capture it so that we can do something about it. The way we do that is by using the asset pipeline. Go to the assets folder, then JavaScript and let's use the tasks.coffee which actually I'm gonna change back to JS. And I'm going to remove all of these comments. Since we are dealing with tasks, I think it's a good idea to place them in here. It makes sense to me. Okay, so let's include the jQuery wrapper so that this code runs when the entire document is loaded. So we're going to have to pick up on that selector which has all of the tasks, and so Task_done. And then for this selector, we're going to capture a change event, and we'll use a function to handle this trigger. Inside this capture, we're going to throw in a new Ajax request. And I'm gonna use the post method because this is the best way of sending a patch request like the one we just want. So what we want to do is have some sort of task/ID/toggle. But as you know JavaScript is not as flexible as Ruby, so we're gonna have to do something like this. We're gonna to go to this event and capture the data's ID. The reason I'm using this sort of notation is because I'm going to store the task's ID as a data attribute in the element. Let's go to views, projects, and then show. And here I'm gonna add in a data attribute, there you go. The ID is going to be the task's ID. I hope you understand what I'm doing here. I'm adding some data into the tag, so the final looks of it will be something like we have the input, and then we're gonna have a data ID equals something. This will be a result that you'll recognize when inspecting the element. We're gonna pick on that using jQuery like this, data and then ID. And we're going to introduce that into the URL to visit. Then we're going to pass in some data, and a call back when it's done. What about this callback? Well, for now I'm going to leave it blank, okay? So we're going to do something about that later. I just want to make sure I have the _method variable injected because I want to specify the exact same method as in the route. Rails already does this, by default, but since we're doing this manually, this is the way to go. What about this function here? What about the callback and what should we do about it? Well, for now we can do nothing at all, because we just want to make sure the behavior is there. So, when we change the data, it should reflect itself again in the browser. So let's try and do that by reloading this page. Actually I'm gonna go and open Firebook so that we can have access to the requests. I'm gonna check the check box and you can see the post method is actually thrown in and we get the 204 status code. Great job. The content is actually nil. It doesn't have anything. So there's no response tag right there. So that's pretty good. Now if we reload the page, you will see that the check box is still checked. So that's pretty good. We have successfully established the way of introducing some JavaScript to our code to improve the functionality, and make it so it's easier for us to check or un-check some tasks. Now, about that callback. I wanna use jQuery UI in order to make this item highlight. You know, like, a little color spike, and then it goes back to normal, the same way as Ruby on Rails did a couple of years ago. I want to use jQuery UI to achieve the same result, so in order to do that I'm going to go ahead and do a couple of things. First of all I want to reach the object, the check box, I'm going to go to the parent element which is the list item, and I want to apply an effect to it. This effect will be available in jQuery UI, which will load right up next. The effect is called highlight. If we do this right away you will see that it won't work. Even though we have a successful request, effect is not a function in jQuery, so we need to fix that by including a gem, first of all. Let's go to the gem file at the root of the project. And I guess right next to the jQuery-rails gem will do the same thing for jquery-ui. jquery-ui-rails is the gem that you should install. So go ahead and type in the bundle command in your terminal to load that. Then we're gonna need to load it in the asset pipeline. The way to do that is by going to, let's see, JavaScript's application JS. And here, we're going to include jquery-ui. If you just wanna load some elements into the asset pipeline, you should check the link that I've posted in the description. Basically it has all the explanations on how to use this gem in Rails. The same way we included the JavaScripts, we need to include the style sheets. Let's go to application.css and use the same instruction, require jquery-ui. And there you go. Now since we added a gem into the gem file, we'll need to cut the server and reload it again. So type in rails server, or s for short, and it will boot the application again with the changes. Let's go to our browser again, reload the page. There you go. It seems like everything is still working. Let's try and click this check box. Okay. So the behavior is still there but I don't see anything in regards to the highlight. I remember now. Let's go back to the editor. You might not be able to recognize this mistake but it's fortunate that I just remembered. Think of the context of this in this function. This one is very different from this one. In this case specifically this is the check box but this this is not the check box. So what we're going to do is create a variable called _this, which will actually be the jQuery object that wraps the check box. Next, we're gonna go to line five and replace this instruction or this variable, with the first one right here. When we do it, we'll be able to reach out to the check box, then the list item, then create the effect. Even though it wasn't throwing any errors, it didn't do what we expected. So, let's reload the page and try to uncheck the box. There you go. I can cycle back and forth in between checking and unchecking the box, you will see a yellow color fading into white again. So there you go. Congratulations on implementing some JavaScript code into the application. The basic steps for a accomplishing such a task are evaluating whether we need a new route or not, creating the respective controller code, make sure we return the specific needed code back to the client, in this case, we didn't need to. And then, we just need to adapt our templates or our view code in order to accommodate such a functionality. We had to add a class and some data into the tag, so we can read it and send information to the server. Then, all we need to do is type in some JavaScript code that does exactly what we expect. In this case, since you wanted to do something when changing a check box, we use this instruction to capture that event and handle it the best way possible.

Back to the top