Unobtrusive JavaScript in Rails

Chuks El-Gran Opia
Backticks & Tildes
Published in
4 min readJan 15, 2018
Photo by Caspar Rubin on Unsplash

JavaScript is a very powerful language; for me, it rules the web. One of the most popular use of JavaScript is updating the content of a page without having to reload the page. This article will focus on how to achieve this in Rails.

I recently picked up Ruby and to familiarise myself with the language, I decided to build a little app using Ruby on Rails. While working on the project, the need to render content on a page without reloading came up. It was a bit frustrating trying to get an article that explains this concept to a newbie, so I decided to write about it.

With most JavaScript codes out there, one would probably need to retrieve data from the server and use JavaScript to manipulate the data on the page but with Rails, it is different as I have come to know.

Rails’ AJAX..

Rails uses a technique called “Unobtrusive JavaScript” to handle attaching JavaScript to the DOM. According to the docs:

We call this ‘unobtrusive’ JavaScript because we’re no longer mixing our JavaScript into our HTML. We’ve properly separated our concerns, making future change easy.

Let’s look at a simple example: Lets assume we have a UsersController and a resource route /user/:name that links to the controller’s index action, we can perform a JavaScript action on a page from the controller.

In the UsersController, add the following code:

class UsersController < ApplicationController
def index
render js: "alert('The username to be displayed is: #{params[:name]}')"
end
end

In your welcome view page, add the following code which should create a “Display a name” link on the page.

<%= link_to 'Display a name', display_path('Troy34'), remote: true %>

Adding remote:true to the link tag tells Rails that you want to make an AJAX request and when we click on the link, a JavaScript alert should pop up on the page displaying The username to be displayed is: Troy34. It’s that simple and it gets even magical in our next example.

Impressive right? Yeah, I know

Just like me, I’m sure you don’t just want to display an alert to your users. Now let’s assume the UsersController’s index action makes some important query and returns an array of users, we would like to display this list of users on our page. For the purpose of this example, I’ll list the files we’ll be referring to, just so things don’t get confusing.

  • Welcome Page: The page with the “Display a name” link to make the AJAX request.
  • index action: The action in the UsersController that queries the database and renders the data.
  • index template: The JavaScript file that targets the element on the page where the list of names should be rendered(located in the user view folder /app/views/users/index.js.erb).
  • _index partial: The file that contains the template to render the names of the users(located in the user view folder as /app/views/users/_index.html.erb)

Back to our second example. From the example above, we already have a link on our Welcome Page that calls the index action of the UsersController. So next, we modify the code in our controller:

class UsersController < ApplicationController
def index
@users = User.all # a random query that returns an array of imaginary users
respond_to do |format|
format.js
end
end
end

In our index template, we add the following code:

$(‘#user-list’).html(“<%= j render(‘index’, users: @users) %>”)

In the above code, we use jQuery to target an imaginary div with the id of user-list where we want to display the list of users. Then we render the content created by a partial called “show” as HTML inside that div. The j is an alias for the Rails method escape_javascript which escapes carriage returns, single and double quotes for JavaScript segments. render(‘index’, users: @users) looks for a partial file named “index” (which we named _index)and passes our @users instance variable to it as a variable called users.

In our _index partial, we add the following code:

<% if !users.empty? %>
<ul>
<% users.each do |user| %>
<li><%= user.name %></li>
<% end %>
</ul>
<% else %>
<div>
<p>User not found</p>
</div>
<% end %>

Our _index partial expects a variable called users (which is coming from the index template). It then loops through our users array and generates a list of users which is then inserted into our user-list div.

So lets run through the events from the point of clicking our “Display a name” link on the index page:

  • Clicking the button makes an AJAX request to the index action of the UsersController
  • The UsersController’s index action makes the query, gets the response from our server and sends it out as js
  • Rails automatically (magically) looks for a template file that corresponds with the index action which is index.js.erb
  • The index template targets an element on the page and renders a partial and passes the users array to the partial
  • The partial loops through the user array and creates the list of users that is rendered on the page

I’m sure right now, you’re marvelling at the elegance at which this was done. This helps you do a lot of amazing things without messing up your view and if the need to change things ever arises, you can do all that in one place.

I hope this has helped you understand how Unobtrusive JavaScript works in Rails. Please 👏 and share.

Thanks!

--

--