By Stephen Huang

How to structure JavaScript code when using AJAX in Rails

AJAX is a great solution that allows you to send and retrieve data from the server and update the page without having to reload the entire page.

In this article I will show you two strategies in Rails to use the data from server by executing JavaScript code: AJAX Callback Function and Server-generated JavaScript Responses. Then I'll explain how they work, and describe their benefits.

Since 5.1, Rails no longer depends on jQuery. A plain JavaScript implementation called rails-ujs replaces jquery-ujs to take advantage of the Unobtrusive JavaScript (UJS) feature in Rails. Although they are implemented in different ways, their concepts are the same. In this article, I will use plain JavaScript for consistency.

Let's start off by creating a Rails app and set it up to send AJAX requests to the server.

Create a AJAX form

Begin with a simple Rails app with a user object:

$ rails new ajax-demo
$ cd ajax-demo
$ rails g scaffold User name:string
$ rake db:migrate

Then we need to create a simple form for that user:


<%= form_with(model: user, id: "new_user", local: true) do |form| %>
<% end %>

<%= tag.div id: "ajax" %>
<%= tag.div id: "sjr" %>

We need to add an id attribute to the form to help us locate form element in JavaScript. We also add two div tags with id that will be used to update page later.

Solution I: Intercept the submit event in JavaScript

To create the AJAX form, the first solution is to add an event handler to intercept the submit event on the form. And then inside the handler, we serialise the form data and create an AJAX request.

# app/assets/javascripts/

  form = document.getElementById("new_user")
  form.addEventListener "submit", (event) ->
    element = this

    # Create a AJAX request
      type: "POST",
      url: "/users",
      data: new FormData(element),
      dataType: 'script',
      success: (args...) ->
        console.log "Ajax callback function"

    Rails.stopEverything event

Solution II: Remote elements

Rails provides a better way to simply build the AJAX form. Supported by rails-ujs, we can use the remote data tag in the form.

The build-in form_with helper includes the remote data tag by default. We can enable AJAX form by removing local: true option. Then the form will be sent as an AJAX request.

# app/views/users/_form.html.erb

<%= form_with(model: user, id: "new_user") do |form| %>
<% end %>

# =>
<form action="/users" id="new_user" method="post" data-remote="true">

dataType attribute

We specify the dataType to tell the server which format we want it to return. When we use a remote form, it will be set to script by default, which means that the server will return a JS response. If we want to receive a JSON response, we can set the dataType to json. For a remote form, we can provide the type using data-type tag.

    dataType: 'script',

# OR
<%= form_with(model: user, id: "new_user", data: { type: "json" }) do |form| %>

The server will return a response based on the dataType. If it's JS and format.js has been enabled, it will render the related js.erb template file.

# app/controllers/users_controller.rb
respond_to do |format|
    format.html { redirect_to @user, notice: 'User was successfully created.' }
    format.json { render :show, status: :created, location: @user }
    format.html { render :new }
    format.json { render json: @user.errors, status: :unprocessable_entity }

Update the page with JavaScript

After the AJAX request is sent, the server will have the data ready for us to be used on the front end. In our Rails app, there are two strategies for doing this: AJAX Callback Function and Server-generated JavaScript Responses (SJR).

Strategy I: AJAX Callback Function

When we use AJAX and receive the response from server, it will trigger the callback functions, such as success, error, etc, based on the status code. The callback functions are defined when we create the AJAX request. You can put your JavaScript code here and it will be executed when it is fired.

# app/assets/javascripts/
  success: () ->
    console.log "Ajax callback function"
    document.getElementById("ajax").innerHTML ="<div>Ajax Success</div>"

You can also put the JavaScript code in the callback function of the event. Unlike jQuery, the Rails AJAX doesn't fire the event for the callbacks by default. However, if you use the remote data tag, the rails-ujs will fire the event for you.

  success: (args...) -> fire(element, 'ajax:success', args)

Then we can add the ajax:success listener and put our JavaScript code in the callback function.

# app/assets/javascripts/
document.body.addEventListener 'ajax:success', (event) ->
  console.log "Ajax event callback function"
  document.getElementById("ajax").innerHTML ="<div>Ajax Success</div>"

Strategy II: Server-generated JavaScript Responses (SJR)

Rails provides another way to execute the JavaScript code: Server-generated JavaScript Responses (SJR), supported by rails-ujs.

After the server has processed the request, it will generate a JavaScript response by rendering the JS template. If you don't specify a template, it will look for the default template file. In our example it is create.js.erb. This template includes our JavaScript code which will be executed after the response is sent to the client.

The Javascript template looks like this:

// app/views/users/create.js.erb
console.log("SJR template");

The template supports ERB which allows you to insert Ruby code. It means we can directly use instance variables, fetch database, call methods, render partials, etc in the template.

Use instance variables:

// app/views/users/create.js.erb
document.getElementById("sjr").innerHTML = "<%= %>";

Render partials:

// app/views/users/create.js.erb
// render user/_user.html.erb
document.getElementById("sjr").innerHTML = "<%= j render @user %>";

escape_javascript method

When we render a HTML partial and use it in a JavaScript template, we need to make sure it is in the correct format. For example, we have a partial _user.html.erb:

<!-- app/views/users/_user.html.erb -->
<div id="name">Name: <%= %></div>

When this template is rendered, it will generate an IO string "<div id=\"name\">Name: Stephen</div>\n" with escape character \ for the special characters. However, when our JS template is rendered, it will also add escape characters. When the client receives the response, it becomes:

"console.log(\"SJR template\");\ndocument.getElementById(\"sjr\").innerHTML = \"<div id=\"name\">Name: Stephen</div>\n\";\n"

After the response is parsed by the client browser, the \n in the HTML string will be treated as a new line in JavaScript, and the double quote in HTML string will be treated as a close quote in JavaScript. This causes the JavaScript code to be incorrectly formatted:

"console.log("SJR template");
document.getElementById("sjr").innerHTML = "<div id="name">Name: Stephen</div>

Fortunately, Rails provides a function called escape_javascript or j to escape the string for JavaScript responses.

j render @user
  Rendered users/_user.html.erb (0.1ms)
# => "<div id=\\\"name\\\">Name: Stephen<\\/div>\\n"

When the client receives the response, this content will be parsed to "<div id=\"name\">Name: Stephen<\/div>\n" which is a valid javaScript string.

Advanced: How the JavaScript code in SJR executes

When the client receives the JS response from the server, rails-ujs will help us to execute our JavaScript code.


processResponse = (response, type) ->
  if typeof response is 'string' and typeof type is 'string'
    if type.match(/\bjson\b/)
    else if type.match(/\b(?:java|ecma)script\b/)
      script = document.createElement('script')
      script.setAttribute('nonce', cspNonce())
      script.text = response
    else if type.match(/\bxml\b/)

From the source code, you can see that our JavaScript code will be added into a new script node. Then the script node will append to the document of the page, which will load immediately. After that, this script node will be removed. That's how the SJR JavaScript code executes.


Both strategies allow you to add your JavaScript code and update the page without a full refresh.

If you only have some simple JavaScript code, you can just put it in the AJAX callback function. It's straightforward and the pure JavaScript way.

However, if your JavaScript code relies on the logic in the server, SJR will be easier to generate the JavaScript code rather than send all the data to client. It simplifies the front-end logic and makes the website faster. Additionally, you can reuse the methods and templates in the Rails framework.

Latest Articles by Our Team

Our expert team of designers and developers love what the do and enjoy sharing their knowledge with the world.

We Hire Only the Best

reinteractive is Australia’s largest dedicated Ruby on Rails development company. We don’t cut corners and we know what we are doing.

We are an organisation made up of amazing individuals and we take pride in our team. We are 100% remote work enabling us to choose the best talent no matter which part of the country they live in. reinteractive is dedicated to making it a great place for any developer to work.

Free Community Workshops

We created the Ruby on Rails InstallFest and Ruby on Rails Development Hub to help introduce new people to software development and to help existing developers hone their skills. These workshops provide invaluable mentorship to train developers, addressing key skills shortages in the industry. Software development is a great career choice for all ages and these events help you get started and skilled up.

  • Installfest


    The Ruby on Rails Installfest includes a full setup of your development environment and step-by-step instructions on how to build your first app hosted on Heroku. Over 1,800 attendees to date and counting.

    Learn more about Installfest

  • Development Hub

    Development Hub

    The Ruby on Rails Development Hub is a monthly event where you will get the chance to spend time with our team and others in the community to improve and hone your Ruby on Rails skills.

    Learn more about Development Hub

  • Webinars


    Webinars are our online portal for tips, tricks and lessons learned in everything we do. Make the most of this free resource to help you become a better developer.

    Learn more about webinars

Get the “reinteractive Review” Monthly Email