
Action Cable Patterns
- 2 installs
- Updated February 9, 2026
- dchuk/rails_ai_agents
Helps with ai & agent building tasks.
About
action-cable-patterns is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- action-cable-patterns
- AI & Agent Building
- AI-coding skill
Action Cable Patterns by the numbers
- 2 all-time installs (skills.sh)
- Ranked #13,956 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/dchuk/rails_ai_agents --skill action-cable-patternsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2 |
|---|---|
| Last updated | February 9, 2026 |
| Repository | dchuk/rails_ai_agents ↗ |
What it does
Helps with ai & agent building tasks.
Files
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
Quick Start
# config/cable.yml
development:
adapter: async
test:
adapter: test
production:
adapter: solid_cable # Rails 8 defaultConnection Authentication
# app/channels/application_cable/connection.rb
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
endChannel Patterns
Pattern 1: Notifications Channel
# app/channels/notifications_channel.rb
class NotificationsChannel < ApplicationCable::Channel
def subscribed
stream_for current_user
end
def self.notify(user, notification)
broadcast_to(user, {
type: "notification",
id: notification.id,
title: notification.title,
body: notification.body
})
end
endPattern 2: Resource Updates Channel
# app/channels/events_channel.rb
class EventsChannel < ApplicationCable::Channel
def subscribed
@event = Event.find(params[:event_id])
if authorized?
stream_for @event
else
reject
end
end
def self.broadcast_update(event)
broadcast_to(event, {
type: "update",
html: ApplicationController.renderer.render(
partial: "events/event", locals: { event: event }
)
})
end
private
def authorized?
EventPolicy.new(current_user, @event).show?
end
endPattern 3: Integration with Turbo Streams
# app/models/comment.rb
class Comment < ApplicationRecord
after_create_commit -> {
broadcast_append_to(
[event, "comments"],
target: "comments",
partial: "comments/comment"
)
}
after_destroy_commit -> {
broadcast_remove_to([event, "comments"])
}
end<%# app/views/events/show.html.erb %>
<%= turbo_stream_from @event, "comments" %>
<div id="comments">
<%= render @event.comments %>
</div>Broadcasting from Services
module Events
class UpdateService
def call(event, params)
event.update!(params)
EventsChannel.broadcast_update(event)
DashboardChannel.broadcast_stats(event.account)
success(event)
end
end
endTesting Channels
Channel Test (Minitest)
# test/channels/notifications_channel_test.rb
require "test_helper"
class NotificationsChannelTest < ActionCable::Channel::TestCase
setup do
@user = users(:one)
stub_connection(current_user: @user)
end
test "subscribes successfully" do
subscribe
assert subscription.confirmed?
end
test "streams for the current user" do
subscribe
assert_has_stream_for @user
end
test "broadcasts notification to user" do
subscribe
notification = notifications(:one)
assert_broadcast_on(
NotificationsChannel.broadcasting_for(@user),
hash_including(type: "notification")
) do
NotificationsChannel.notify(@user, notification)
end
end
endChannel with Authorization Test
# test/channels/events_channel_test.rb
require "test_helper"
class EventsChannelTest < ActionCable::Channel::TestCase
setup do
@user = users(:one)
@event = events(:one) # belongs to @user's account
@other_event = events(:other_account)
stub_connection(current_user: @user)
end
test "subscribes to authorized event" do
subscribe(event_id: @event.id)
assert subscription.confirmed?
assert_has_stream_for @event
end
test "rejects unauthorized event" do
subscribe(event_id: @other_event.id)
assert subscription.rejected?
end
endConnection Test
# test/channels/connection_test.rb
require "test_helper"
class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase
test "connects with valid session token" do
user = users(:one)
session = user.sessions.create!
connect cookies: { session_token: session.token }
assert_equal user, connection.current_user
end
test "rejects without session token" do
assert_reject_connection do
connect
end
end
endStimulus Controller for Channels
// app/javascript/controllers/chat_controller.js
import { Controller } from "@hotwired/stimulus"
import consumer from "../channels/consumer"
export default class extends Controller {
static targets = ["messages", "input"]
static values = { roomId: Number }
connect() {
this.channel = consumer.subscriptions.create(
{ channel: "ChatChannel", room_id: this.roomIdValue },
{
received: this.received.bind(this),
}
)
}
disconnect() {
this.channel?.unsubscribe()
}
received(data) {
if (data.type === "message") {
this.messagesTarget.insertAdjacentHTML("beforeend", data.html)
this.messagesTarget.scrollTop = this.messagesTarget.scrollHeight
}
}
send(event) {
event.preventDefault()
const body = this.inputTarget.value.trim()
if (body) {
this.channel.perform("speak", { body })
this.inputTarget.value = ""
}
}
}Checklist
- [ ] Connection authentication configured
- [ ] Channel authorization implemented
- [ ] Channel tests written
- [ ] Broadcasting from services/models
- [ ] Client-side subscription set up
- [ ] Turbo Stream integration (if applicable)
- [ ] All tests GREEN
Related skills
AI & Agent Buildingagents