Channels 101
While
stream_from
is great, there are many techniques only possible if you leverage ActionCable Connections, Channels and Subscriptions.CableReady v5 introduced the
stream_from
helper, which was covered in the previous Hello World chapter.There's an entire chapter dedicated to explaining ActionCable, but this should be enough to get started. 😅
An ActionCable Channel is a Ruby class you create with a goal in mind. Achieving that goal revolves around sending and receiving messages from a list of subscribers that are connected over WebSockets.
Channels define one or more unique identifiers. These are string patterns which map subscribers to Channels, similarly to how
routes.rb
maps request paths to Controllers. The way you structure these identifiers decides whether messages sent to the Channel are delivered to every subscriber, or just a subset that matches a given pattern.On the client, you use an ActionCable Connection
consumer
to subscribe to Channels. The subscription provides access to data that is received
from the server, as well as a mechanism for sending data to the sever.The subscription attempt can optionally include
params
, similar to POSTing a form to a controller action. The Channel class can access these params
and use these values to compute and return a subscription identifier. Don't worry if this sounds complicated, because we're going to create a Channel together, now.
Use the Rails
channel
generator to create an ActionCable Channel class called ExampleChannel
. If this is the first time you've generated a Channel, a number of important files and folders will be created.rails g channel example
In this configuration, every client that subscribes to
ExampleChannel
will receive any broadcasts sent to to the identifier visitors
. Operations broadcast there will be sent to everyone looking at your site. They will be automatically subscribed to your channel.app/channels/example_channel.rb
class ExampleChannel < ApplicationCable::Channel
def subscribed
stream_from "visitors"
end
end
The generator also creates a JavaScript channel subscriber. Import
CableReady
and modify the received
method to check incoming data for CableReady broadcasts.app/javascript/channels/example_channel.js
import CableReady from 'cable_ready'
import consumer from './consumer'
consumer.subscriptions.create('ExampleChannel', {
received (data) {
if (data.cableReady) CableReady.perform(data.operations)
}
})
Thanks to Turbo Drive / Turbolinks, subscriptions created in this manner will remain active until the user refreshes the page or leaves the site.
Now that we have created a Channel, it's time to send commands to the client.
You can use CableReady almost anywhere in your application, so long as you include it in the class that you're working in:
include CableReady::Broadcaster
On the CableReady Everywhere page, you'll learn how to broadcast from (pretty much) anywhere in your application.
With few exceptions, all CableReady invocations have three predictable segments:
- 1.Stream identifier(s): who (or what) will receive operations
- 2.Operation queueing: one or more operations to broadcast
- 3.Broadcast: deliver all queued operations immediately
class User < ApplicationRecord
include CableReady::Broadcaster
after_create do
cable_ready["visitors"] # send to everyone subscribed to the channel streaming from "visitors"
.console_log(message: "Welcome #{self.name} to the site!") # all users will see a message appear in their browser's Console Inspector
.broadcast # send all queued operations to all ExampleChannel subscribers
end
end
The
ExampleChannel
that you created will send any operations broadcast to visitors
to all currently subscribed clients. In the code above, everyone on the site will see a Console Inspector message welcoming the latest member.ActionCable can deduce
ExampleChannel
from visitors
because only one Channel can stream from a given identifier. It is conceptually similar to Rails request routing, except that identifiers are defined inside of your Channel classes.CableReady maintains a queue of operations for every identifier. You can call
cable_ready
multiple times to add more operations to these queues.cable_ready
is a singleton instance, which means that you can keep adding operations to a queue across multiple method calls.cable_ready["visitors"].console_log(message: "We have more salad than we can eat.")
cable_ready["visitors"].set_style(selector: "body", name: "color", value: "red")
You can use different operations together, and each operation can have completely different options. The most common option is
selector
, which is how you identify the target DOM element(s) for an operation. In fact, it's so common that you can just pass it as the first parameter, without a key.cable_ready["visitors"].set_style("#foo", name: "color", value: "blue")
Operations will continue to accumulate for all stream identifier queues until you call
broadcast
.When you call
cable_ready["visitors"]
, it returns a CableReady::Channels
object, which supports method chaining. That is, you can link up as many operations in sequence as you want, and they will be broadcast in the order that they were created.cable_ready["visitors"].console_log(message: "1").console_log(message: "2")
The
broadcast
method concludes the chain. After the operations have been dispatched, the queues are emptied.cable_ready["visitors"].console_log(message: "Welcome!").broadcast
That's really all you need to get started with CableReady.
You can look over the next sections to learn more techniques, such as broadcasting to resources, or jump to the Operations reference and see everything CableReady can do.

Last modified 1yr ago