About action-cable
A setup guide for ActionCable in Rails applications, covering authenticated WebSocket connections, channels, and Turbo Streams broadcasting for developers building real-time updates.
Key features
- 01Configure ActionCable connections and channels
- 02Authenticate connections with Devise/Warden
- 03Broadcast updates with Turbo Streams
- 04Set cable adapters and routes
- 05Inspect connection status and enable logs
Use cases
- 01Add real-time notifications to an app
- 02Broadcast organization-scoped timer updates
- 03Troubleshoot WebSocket connections
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ rolemodel/ rolemodel-skills --skill action-cableAfter installing, type/action-cablein Claude Code to confirm it loaded.
Details
From the project READMEActionCable Setup
Overview
ActionCable integrates WebSockets with Rails to enable real-time features. This guide covers the basic setup in this application.
Core Components
1. Connection (app/channels/application_cable/connection.rb)
The connection authenticates and authorizes the WebSocket connection using Devise/Warden.
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
end
private
def find_verified_user
if verified_user = env['warden'].user
verified_user
else
reject_unauthorized_connection
end
end
end
end
2. Channel (app/channels/application_cable/channel.rb)
Base channel class for all application channels.
module ApplicationCable
class Channel < ActionCable::Channel::Base
end
end
3. JavaScript Setup (app/javascript/initializers/actioncable.js)
Initialize ActionCable consumer on the client side.
import * as ActionCable from '@rails/actioncable'
ActionCable.logger.enabled = false
Broadcasting Updates
With Turbo Streams (recommended)
Subscribe to a stream in views:
= turbo_stream_from record
= turbo_stream_from [record, "channel_name"]
Broadcast Turbo Stream updates from controllers or background jobs:
# Append content to a target
Turbo::StreamsChannel.broadcast_append_to(
[record, "channel_name"],
target: "dom_id",
partial: "path/to/partial",
locals: { record: record }
)
# Replace content
Turbo::StreamsChannel.broadcast_replace_to(
[record, "channel_name"],
target: "dom_id",
partial: "path/to/partial",
locals: { record: record }
)
# Remove element
Turbo::StreamsChannel.broadcast_remove_to(
[record, "channel_name"],
target: "dom_id"
)
Example: Organization-scoped notifications
View:
= turbo_stream_from current_organization, "timers"
#notifications
Controller:
def start_timer
# ... create timer logic ...
Turbo::StreamsChannel.broadcast_append_to(
[current_organization, "timers"],
target: "notifications",
partial: "timers/notification",
locals: { timer: @timer }
)
end
Configuration
Cable URL (config/cable.yml)
development:
adapter: async
test:
adapter: test
production:
adapter: solid_cable
connects_to:
database:
writing: cable
polling_interval: 0.1.seconds
message_retention: 1.day
Routes (config/routes.rb)
ActionCable is automatically mounted at /cable:
Rails.application.routes.draw do
mount ActionCable.server => '/cable'
end
Debugging
Enable logging in development:
// app/javascript/initializers/actioncable.js
ActionCable.logger.enabled = true
Check connection status:
const subscription = consumer.subscriptions.create("ExampleChannel", {
connected() {
console.log("Connected to ExampleChannel")
}
})
console.log(subscription)
Security Considerations
- Always authenticate connections in
ApplicationCable::Connection - Validate params in channel subscriptions
- Use
stream_forinstead ofstream_fromwhen possible for automatic scoping - Never trust client-side data without validation
- Consider rate limiting for channels that accept client messages