The normal flow of visiting a website is that you load a page & if you want to see new information you have to either reload the page to update it, or click a link to visit a different page.

This a synchronous flow.

New data is only presented when a new page is requested from the server.

But…

What if you don’t want this page reload?

What if you want to fetch data from the backend, at any time you want, so that you can update any part of the current page?

This is where AJAX comes in.

AJAX stands for Asynchronous Javascript & XML.

It’s a technique that’s independent of your web framework, but Rails specifically has good support for it as you’ll learn in this article.

Keep in mind that adding AJAX into your app makes it more complex.

Direct AJAX Request

AJAX has two parts, the request, which you make from the browser using Javascript, and the response, which you handle from your Ruby app.

You can make an AJAX request with plain Javascript.

But because that requires a lot of boilerplate code we usually do this through a Javascript library like jQuery.

Here’s what a jQuery request looks like:

$.get( "/vegetables", function(data) {
  alert("Vegetables are good for you!");
});

However, since Rails 5.1 jQuery is not available by default (but you can add it back).

Note: You’ll get an InvalidAuthenticityToken error when you do a jQuery POST request, this means that you need to submit the csrf-token from the current page as a security measure. Using Rails.ajax does this for you automatically.

There is a solution!

Rails includes its own AJAX function:

Rails.ajax({
  url: "/books",
  type: "get",
  data: "",
  success: function(data) {},
  error: function(data) {}
})

Remember, this is still from the request side of things, from the browser.

Meaning that this is Javascript code.

In Rails, this AJAX functionality is provided by something called “Unobtrusive JavaScript”, or “UJS” for short.

Updating a Partial with AJAX

If you want to update only part of your page with the data you get from AJAX, you have mostly two options.

  1. You can write a Javascript + ERB view, which updates the element
  2. You can return a JSON response from your controller with the new HTML as a string, then use Javascript to update the element

There is also a 3rd option.

It involves returning only the data as JSON, then generating the HTML elements with Javascript using that data.

This is where JS frameworks like React come in.

In my opinion they add a lot of unnecessary complexity.

But we can handle this with plain Javascript!

That’s options 1 & 2.

Let’s stick with those for now 🙂

Javascript view example:

Rails.$('.random-number')[0].innerHTML = ("<%= j="" (render="" partial:="" 'random')="" %="">")

j is an alias for escape_javascript

jQuery example:

$('.random-number').html("<%= j="" (render="" partial:="" 'random')="" %="">")

Both html & innerHTML replace the contents of the target element.

You could also append (jQuery) a new element into a list instead of replacing the whole thing.

Put this code in a file with an extension of .js.erb, with the name of the current action (like create.js.erb) & inside the views folder.

On the controller you can render this view just like any other view.

Now:

When you make an AJAX call, this Javascript code will run automatically & update the HTML.

Let’s have a look at the 2nd option.

Here’s the controller code:

render json: { html: render_to_string(partial: 'random') }

Then from your Javascript code:

Rails.ajax({
  url: "/books",
  type: "get",
  success: function(data) { Rails.$(".random-number")[0].innerHTML = data.html; }
})

That’s another way to do this!

What should you use?

DHH’s favorite is the first way, which he calls “SJR” (Server-Generated Javascript).

I guess this is how Rails wants you to do this, but feel free to try both (SJR & render_to_string) yourself & see which one works best for you.

How to Use HAML For Your JS Views

Ok.

Let’s say you’re a HAML user.

Is it possible to use this SJR technique & render .js.haml views?

Yes!

Here’s an example:

- content = j (render partial: "random")

Rails.$('.random-number')[0].innerHTML = ("#{content}")

It’s a bit uglier than the ERB version, but it works.

How to Submit a Rails Form Without Refreshing The Page

If you want to submit a form using AJAX you can do this without having to write an AJAX request.

Rails can handle it for you.

How?

Use the remote: true option with form_for.

Here’s an example:

<%= form_for="" @fruit,="" remote:="" true="" do="" |f|="" %="">
  <%= f.label="" :name,="" 'fruit'="" %="">
  <%= f.text_field="" :name="" %="">

  <%= f.submit="" 'create'="" %="">
<% end="" %="">

Now when you click “Create” Rails will send an AJAX request for you & the page won’t reload.

If you want to display validation errors you’ll have to create & render a Javascript view (.js.erb file) that replaces the current errors with the new errors.

Like the example in “Updating a Partial with AJAX”.

Btw, this remote option can also be used with links, so you can do an AJAX delete request.

Example:

<%= link_to="" "delete",="" book_path(book),="" {="" method:="" remote:="" true,="" data:="" confirm:="" "are="" you="" sure?"="" }="" <="" pre="">

You can handle the response using a Javascript view.

If you want to handle both HTML requests (coming from a page reload) & AJAX request, you'll have to use something like the respond_to method.

Example:

respond_to do |f|
  f.html { redirect_to :index }
  f.js
end

In this example it may be easier to let Turbolinks handle this.

You can still do the AJAX requests & a redirect_to from the controller (without respond_to), then Turbolinks will replace the contents of the page without reloading it.

AJAX Not Working? Here Are Some Tips

If your AJAX request is not working then you have some debugging to do.

First, open your browser developer tools.

You want to look at the console panel for any Javascript errors.

Fix those.

Also, make sure that any CSS selector you're targeting is right & you don't have any typos.

Then, check your rails logs for any errors.

Then, make sure that the correct view is being rendered.

If you follow this process you should be able to find why your AJAX request is not working & fix it.

Summary

You have learned about AJAX, a web development technique that allows you to make Asynchronous Request!

You have also learned how to implement this in Rails. Remember that AJAX isn't required to make your regular (non-JS framework) Rails app work, but it's something that is helpful to have in your toolbox.

Don't forget to share this article so more people can benefit from it 🙂

Thanks for reading!