Stimulus and ActionCable

The Turbo ActionCable helpers are useful, but they don’t cover every use case for ActionCable. We may need to use ActionCable by using custom JavaScript on the client, either because there is an already existing endpoint or because our task doesn’t quite fit the Turbo patterns. In this lesson, we’re going to use ActionCable to rebuild the “sold out” feature we previously built using polling in.

To use ActionCable directly, we need to create objects on the client and the server.

ActionCable on the server-side

On the server, we have channels and connections.

ActionCable channel

An ActionCable channel is roughly analogous to a Rails controller. The channel is where we put the code that responds to data the server receives over the socket and where we set up the structure of the data being sent to the client. Turbo created a generic channel for us to use, but we’re going to build a custom one.

ActionCable connection

The connection class is more abstract. It’s used by the channel and typically handles authorization. In setting up our project, Rails created the two top-level classes, ApplicationCable::Connection and ApplicationCable::Channel, that we can use as base classes.

ActionCable on the client-side

On the client-side, we’ll call a method called createConsumer that returns a data object that we can use to subscribe to a specific server-side channel, and then specify what we want to happen in response to received data.

Using ActionCable

Let’s look at an example of using ActionCable to broadcast sold-out concert data to our schedule page. We’ll need to write some server-side and client-side code. On the server-side, we need to create a channel and set up the place where data is sent to that channel. On the client-side, we need to respond to data when it’s sent.

We’ve set this functionality up to be as basic as possible: the data only flows one way from the server to the client and the identical broadcast goes to all subscribers. The schedule is the same for everybody.

We can start by asking Rails to generate some boilerplate:

% rails generate channel ScheduleChannel

This will generate a server-side file, app/channels/schedule_channel.rb, a test file in spec/channels/schedule_channel_spec.rb (since we have RSpec installed); and a client-side file, app/packs/channels/schedule_channel.js.

Note: A mismatch between Rails and Webpacker 6 is still possible and Rails may try to create the JavaScript files in a different directory (app/javascript). If so, you’ll need to move all of them to app/packs.

If this is your first ActionCable Rails generation, Rails will also create an index.js file for app/packs/channels. Like the similar file created for Stimulus controllers, this will automatically load any file in that directory ending in _channel.js. Rails will also create a file at app/packs/channels/consumer.js, which is a shortcut for calling the ActionCable method createConsumer. We are going to ignore these boilerplate files and integrate ActionCable ourselves.

On Server-Side

The first thing we need to do on the server-side is to define the channel. The channel does not do much here:

Get hands-on with 1200+ tech skills courses.