How to Use Action Cable With an API-only Application

Stephen McBride
3 min readNov 30, 2020
https://pixabay.com/photos/aerial-air-alpine-cabin-cable-car-15960/

One technology I’ve wanted to learn since the start of my Flatiron boot camp experience was WebSockets. Recently I started working on a project that featured real-time collaboration, and the only real way I saw this feature working was through the use of web sockets. The project is currently built using Rails for the backend, so I needed to find a way to use WebSockets with Rails. Fortunately, after some research, I found out that Rails has the perfect solution for this: Action Cable.

In a nutshell, Action Cable in Rails contains the functions for both the server and the client. This is nice for projects that use Rails for both the frontend and the backend. However, in my instance, this was an issue since I was only using Rails as an API. After reading some documentation, doing some research, and debugging some issues, I got Action Cable working. Here's how you can do it yourself!

For this example project, I’m going to be creating a simple chat app, similar to the one demonstrated in the Action Cable documentation. The main purpose of this blog post is to explain the setup process of Action Cable, so this is geared more toward developers that already have experience with Action Cable. If you’re looking to learn the basics, I recommend Samuel Mullen’s article, which covers everything from lifecycle to setup.

Backend

The first thing you want to do is to mount Action Cable, either in your routes.rb file or in your application.rb file.

In application.rb:

# config/application.rb
module ActioncableExampleBackend
class Application < Rails::Application
config.action_cable.mount_path = '/websocket'
end
end

OR

In routes.rb:

# config/routes.rb
Rails.application.routes.draw do
mount ActionCable.server => '/cable'
end

The next step is something that had me stuck for a while. Just like with HTTP requests, origin matters. I originally set up CORS using the rack-cors gem and assumed that it would cover web socket requests as well. However, in my case, this did not work. I eventually found out that in order to allow local requests I needed to add the following line to my config/environments/development.rb file:

# config/environments/development.rb
config.action_cable.allowed_request_origins = [/http:\/\/*/, /https:\/\/*/, /file:\/\/*/]

Normally request origin issues are handled with CORS. However, since this is not HTTP and is instead WebSockets, this needs to be handled by inserting the above line into the development environment file. This way, any requests from sites using HTTP/HTTPS, as well as local files opened in a browser (FILE) can be allowed.

Frontend

One great thing about Action Cable is that the Rails team created an NPM package that you can use with your frontend projects. It handles a lot of the nitty-gritty of WebSockets for you and provides you with a neat and easy way to communicate between the server and client.

The first step to using the NPM package is to install it in your project:

npm install actioncable

After the installation process is complete, import/require the Action Cable module wherever you’re going to use it:

const ActionCable = require('actioncable');

If for some reason you cannot import Action Cable, the way I found around this was to add a bundler to your application and use require instead, as shown in the example above.

ActionCable.createConsumer(‘ws://localhost:3000/cable’);

One other important point is that whenever you create a consumer, you need to make sure that the address you provide matches your backend address/port.

After this, your project is basically set up! All you need to do now is to run/update your backend, run your frontend, and both should work perfectly. I’m still very new to Action Cable, so if I got something wrong or if there’s a better way of doing something, please let me know!

--

--