| name | action-cable-patterns |
| description | Implements real-time features with Action Cable and WebSockets. Use when adding live updates, chat features, notifications, real-time dashboards, or when user mentions Action Cable, WebSockets, channels, or real-time. WHEN NOT: Simple HTTP request/response flows, REST APIs, static content, or features that don't need real-time updates. |
| paths | app/channels/**/*.rb, app/javascript/channels/**/*.js, spec/channels/**/*.rb |
Action Cable Patterns for Rails 8
Overview
Action Cable integrates WebSockets with Rails:
- Real-time updates without polling
- Server-to-client push notifications
- Chat and messaging features
- Live dashboards and feeds
- Collaborative editing
Quick Start
Action Cable is included in Rails by default. Configure it:
development:
adapter: async
test:
adapter: test
production:
adapter: solid_cable
adapter: redis
url: <%= ENV.fetch("REDIS_URL") %>
Project Structure
app/
āāā channels/
ā āāā application_cable/
ā ā āāā connection.rb # Authentication
ā ā āāā channel.rb # Base channel
ā āāā notifications_channel.rb
ā āāā events_channel.rb
ā āāā chat_channel.rb
āāā javascript/
ā āāā channels/
ā āāā consumer.js
ā āāā notifications_channel.js
ā āāā events_channel.js
spec/channels/
āāā notifications_channel_spec.rb
āāā events_channel_spec.rb
Connection Authentication
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 session_token = cookies.signed[:session_token]
if session = Session.find_by(token: session_token)
session.user
else
reject_unauthorized_connection
end
else
reject_unauthorized_connection
end
end
end
end
Channel Patterns
Four core patterns are available. See channel-patterns.md for full Ruby and JavaScript implementations:
- Pattern 1: Notifications Channel ā streams per-user notifications via
stream_for current_user
- Pattern 2: Resource Updates Channel ā streams updates for a specific resource with authorization via
reject
- Pattern 3: Chat Channel ā bidirectional messaging with
speak and typing actions, presence tracking
- Pattern 4: Dashboard Live Updates ā broadcasts stats and activity feed to all account members
Each pattern follows the same structure:
subscribed ā find the resource, check authorization, call stream_for
- Class-level
broadcast_* methods ā render partials via ApplicationController.renderer
- A matching JavaScript subscription handler with a
received(data) switch
Broadcasting
Broadcasting can be triggered from services, models, or callbacks. See broadcasting-and-stimulus.md for:
- From a service object ā call
EventsChannel.broadcast_update(event) after persistence
- From model callbacks ā use
after_create_commit to trigger channel broadcasts
- Turbo Streams integration ā use
broadcast_append_to / broadcast_remove_to helpers directly on models
- Stimulus controller ā wrap the Action Cable subscription lifecycle inside a Stimulus controller for clean connect/disconnect management
- Performance patterns ā connection limits, selective broadcasting, debounced broadcasts
Testing Channels
See testing.md for full specs. Key conventions:
stub_connection(current_user: user)
subscribe(event_id: event.id)
expect(subscription).to be_confirmed
expect(subscription).to have_stream_for(event)
expect(subscription).to be_rejected
expect {
described_class.notify(user, notification)
}.to have_broadcasted_to(user).with(hash_including(type: "notification"))
Checklist
References
- channel-patterns.md ā Full implementations of Notifications, Resource Updates, Chat, and Dashboard channels (Ruby + JavaScript)
- broadcasting-and-stimulus.md ā Broadcasting from services/models, Turbo Streams integration, Stimulus controller, performance tips
- testing.md ā RSpec channel specs, authorization specs, and system tests