Rails shipped without jQuery as a dependency for the first time with version 5.1. Rails used to rely on jQuery for Unobtrusive JavaScript features but now ships with its own library rails-ujs with the same features.

One of the most common use cases for jQuery in Rails was making AJAX calls through forms and links. If you’re using Rails 5.1 for the first time, you might get confused about how to make AJAX calls, especially things like data formats and including CSRF tokens.

So this little tutorial walks you through a few ways you can do so.

If you're using a standard Rails form or link for AJAX calls, Rails still offers some great in-built methods. However, when you're not using those methods, for example when you're building a React UI for a Rails app, then you will find this tutorial helpful.

1. Use rails-ujs (no jQuery)

A new Rails 5.1 app automatically includes the rails-ujs script in the app’s application.js file:

//= require rails-ujs
If you don’t want to include it there and use it only selectively, say if you’re making a separate React frontend with Rails’s new webpacker support, then you can do use rails-ujs by installing it as a package:

$ yarn add rails-ujs
And then import and start it in your JavaScript file:

import Rails from 'rails-ujs'
Rails.start()
Remove this line from application.js :

//= require rails-ujs
Now let’s say we want to make an AJAX POST call to an API endpoint/things with some data which looks like this:

mydata = {
 thing: {
  field1: value1,
  field2: value2,
}}
Making an AJAX POST call with rails-ujs looks identical to making it with jQuery:

Rails.ajax({
  type: "POST", 
  url: "/things",
  data: mydata,
  success: function(repsonse){...},
  error: function(repsonse){...}
})
Except for one thing! As far as I can tell, you can’t simply send JSON data. So we need to convert mydata to application/x-www-form-urlencoded content type manually like this:

mydata = 'thing[field1]=value1&thing[field2]=value2'
jQuery does this conversion automatically before submitting a request.

I assumed rails-ujs has some automatic way of doing it, but I couldn’t find anything in the docs or code.

If you know, let me know.

rails-ujs automatically takes care of including the CSRF token with the request.


2. Use jQuery

If the manual data conversion puts you off, you can still use jQuery. You may be relying on jQuery for other things in your app anyway, so here are couple of ways of using jQuery with Rails for making AJAX calls:

2.1 Use the jquery-rails gem

This gem used to be automatically included in previous versions of Rails. You can install it by adding it to your Gemfile:

gem 'jquery-rails'
Then run:

$ bundle install
And include jquery and jquery_ujs in your application.js file:

//= require jquery
//= require jquery_ujs
That’s all you need. Now you can make your AJAX call in the usual way:

$.ajax({
  type: "POST", 
  url: "/things",
  data: mydata,
  success: function(data, textStatus, jqXHR){...},
  error: function(jqXHR, textStatus, errorThrown){...}
})
jquery_ujs takes care of including the CSRF token and jquery converts the data to application/x-www-form-urlencoded content type automatically.

2.2. Use jquery package from npm

If you don’t want to use a gemified version of jQuery, you can install it as a JavaScript package from npm:

$ yarn add jquery
$ yarn add jquery-ujs
Then import them in your JavaScript file:

import $ from ‘jquery’
import {} from ‘jquery-ujs’
Make sure to remove the jquery-rails gem if you have it installed and remove jquery and jquery_ujs from application.js. 

You may get an error saying jQuery is not defined. In your webpack config file add this to the config.plugins array:

new webpack.ProvidePlugin({
 $: “jquery”,
 jQuery: “jquery”
}),
And now you will be able to use jQuery for making your AJAX calls.

3. Use axios

axios is a promise-based HTTP library. You can use it to make HTTP requests from node.js (on the server) and also AJAX requests from the browser.

It’s a good alternative if you don’t need any of jQuery’s other features. To use axios in a Rails 5.1 app (with webpacker), install it:

$ yarn add axios
Then import it in your JavaScript file:

import axios from ‘axios’
Now we can make the AJAX call like this:

axios({
  method: 'POST', 
  url: '/things',
  data: mydata,
  headers: {
    'X-CSRF-Token': document.querySelector("meta[name=csrf-token]").content
  }
})
.then(function(response) {...},
.catch(function(error) {...}
})
A few things to note here:

We have to include the CSRF token header. Unlike jquery_ujs and rails-ujs, it’s not automatically included with axios requests.

We can specify it as a default setting to avoid repeating it in all our AJAX calls:

const csrfToken = document.querySelector("meta[name=csrf-token]").content
axios.defaults.headers.common[‘X-CSRF-Token’] = csrfToken
We can access the success and error responses using the promises syntax .then.

Another option is to use fetch, but it’s an experimental API and not available by default in all browsers. So you’re best off using Github’s polyfill library. I prefer axios to fetch because fetch responses need to be first converted to json and the error handling can also be confusing.