Ajax Calls in Rails, Delete Actions Without Reloading the Page

Franklin Bado
The Startup
Published in
5 min readSep 17, 2020

Rails is great when implementing CRUD for our models, (Create, Read, Update, and Destroy). It is well structured for the developer to be in control of the data that the application has to offer and to what access allows for the user on what to do with such data.

Using the controllers and defining the methods in there grants the user the flexibility to do all these actions, but in order to see the changes, the page needs to reload, and there is nothing wrong with that, but it will be nicer if we can make these actions more dynamic and allow the application to behave more like other sites where there is no need for reloading the page is truly beneficial.

As I dive into javascript, I am learning the use of functions and events, and there is a new concept I am exploring called Ajax calls.

AJAX, based on w3schools refers to ‘Asynchronous JavaScript And XML’. Ajax allows web pages to be updated asynchronously by exchanging data with a web server behind the scenes. This means that it is possible to update parts of a web page without reloading.

How AJAX Works

source = https://www.w3schools.com/xml/ajax_intro.asp

I will be using the above method in this blog to call on the delete action on my application and to delete the selected data without the need of reloading the page.

One way to delete an instance of a class without reloading the page.

For this mechanism to work, the idea is to communicate with the back-end via javascript on the front-end. The server is responsible for generating the JSON code to respond to the client on the front-end.

Rails can make use of JSON Response using the concept of remote true, this is enabled by default in rails, and it will reduce the amount of Js code for the action to work.

#/app/contollers/students_controller.rb
class StudentsController < ApplicationController
...def destroy
@student = Student.find(params[:id])
@student.destroy
#It will dictate what format the action will respond to
respond_to do |format|
format.html
# when responding to a html request, it will respond by going into /app/views/students/destroy.html.erb format.js
#when responding to a json request, it will respond by generating js code located in /app/views/students/destroy.js.erb
end
end
...
end

It all depends on how we set the respond_to, on which method, and what is the end goal for the call.

# /app/views/instructors/index.js.erb

let instructorsUl = document.querySelector("ul#instructors")

# Ruby code will get executed, and this will communicate with the front-end via javascript.
<% @instructors.each do |instructor| %>
instructorLi = document.createElement("li")

instructorLi.id = "instructor-<%= instructor.id %>"
instructorLi.innerText = "<%= instructor.first_name %>"

instructorsUl.append(instructorLi)
<% end %>

At this moment my application students#index looks like this

# /app/views/students/index.html.erb<% @students.map do |student_info| %>
<tbody id="deleteStudent<%= student_info.id %>">
<tr class="text-center"> <br>
<td class="text-center"><%= link_to student_info.id, student_path(student_info), :class => 'btn btn-default' %></td>
<td><%= student_info.name.capitalize %></td>
<td><%= student_info.language %></td>
<td> <%= student_info.age %> </td>
<td><%= link_to(student_path(student_info), method: :delete, remote: true) do %>
<p class="text-center"><span class="glyphicon glyphicon-trash"></span></p>
<% end %>
</td>
</tr>
</tbody>
<% end %>

Above, the bold lines of code are in charge of communicating what is happening in the back-end to the front-end, in order words, when I delete a student instance, I need the front-end to reflect such change without the need for the user to reload the page.

For that to work, I need to create the logic in the destroy.js.erb that I call on from the Student controller.

# /app/views/students/destroy.js.erblet delete<%= @student.id %> = document.querySelector("#deleteStudent" + <%= @student.id %>);delete<%= @student.id %>.remove();

By having the action of destroy defined in the controller, I am allowing the user once they clicked on the button, to make the request for the delete action. As explained by Erin “when adding rails helper remote: true this stops the default action of the object (known as preventDefault() in Javascript) and instead performs the Ajax call. You are still required to provide a path that points to the appropriate action corresponding to the correct HTTP request.”

Once the appropriate path has been given, the action goes to the controller method and looks for the view where is it been sent to, in this case, it is going to be rendered to format.js which points to the destroy.js.erb. This view is telling the application to look for an id tag of deleteStudent that has the student.id attached to it, and once it finds it, it is telling it to remove it.

Students_contorller
Students#index — since I want to be able to delete the instance of a student from this view
destroy.js.erb for Students#view

Conclusion

The delete action still depends on the controller and the method destroy, what I have accomplished here by adding the Ajax call, is for this action to occur without the need of reloading the page. Without the destroy.js.erb the student instance still gets deleted from the database, but for the user to see such change, the page needs to be reloaded. With destroy.js.erb the user experience is enhanced by removing the extra step.

Demo for deleting action using Ajax call on the Student Model

Resources

--

--

Franklin Bado
The Startup

Fellowship Student at Flatiron School, detailed-oriented learning code one step at the time. I enjoy learning how things work, and improving their functionality