action-cable-realtime

This skill should be used when the user asks about Action Cable, WebSockets, real-time features, channels, broadcasting, subscriptions, chat applications, live notifications, presence indicators, collaborative editing, server push, pub/sub patterns, Solid Cable, or streaming updates. Also use when discussing real-time architecture, WebSocket deployment, or alternatives like polling and Server-Sent Events. Examples:

16 stars

Best use case

action-cable-realtime is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

This skill should be used when the user asks about Action Cable, WebSockets, real-time features, channels, broadcasting, subscriptions, chat applications, live notifications, presence indicators, collaborative editing, server push, pub/sub patterns, Solid Cable, or streaming updates. Also use when discussing real-time architecture, WebSocket deployment, or alternatives like polling and Server-Sent Events. Examples:

Teams using action-cable-realtime should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/action-cable-realtime/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/development/action-cable-realtime/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/action-cable-realtime/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How action-cable-realtime Compares

Feature / Agentaction-cable-realtimeStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

This skill should be used when the user asks about Action Cable, WebSockets, real-time features, channels, broadcasting, subscriptions, chat applications, live notifications, presence indicators, collaborative editing, server push, pub/sub patterns, Solid Cable, or streaming updates. Also use when discussing real-time architecture, WebSocket deployment, or alternatives like polling and Server-Sent Events. Examples:

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Action Cable & Real-Time: WebSockets in Rails

## Overview

Action Cable integrates WebSockets with Rails, enabling real-time features like chat, notifications, and live updates. It provides both server-side Ruby and client-side JavaScript frameworks that work together seamlessly.

**Action Cable enables:**
- Real-time chat and messaging
- Live notifications
- Presence indicators (who's online)
- Collaborative editing
- Live dashboard updates
- Real-time feeds

Rails 8 introduces **Solid Cable**, which replaces Redis with database-backed pub/sub, simplifying deployment.

## Core Concepts

### WebSockets vs HTTP

**HTTP (Request-Response):**
```
Client → Request → Server
Client ← Response ← Server
[Connection closes]
```

**WebSocket (Persistent Connection):**
```
Client ↔ Persistent Connection ↔ Server
[Messages flow both directions]
[Connection stays open]
```

Benefits:
- Bi-directional communication
- Low latency (no connection overhead)
- Server can push to clients
- Efficient for real-time features

### Action Cable Architecture

```
Browser (Consumer) → WebSocket → Connection → Channels → Broadcasters
```

**Connection**: WebSocket connection (one per browser tab)
**Channel**: Logical grouping (like a controller)
**Subscription**: Consumer subscribed to a channel
**Broadcasting**: Message sent to all channel subscribers

## Channels

Channels are like controllers for WebSockets.

### Creating a Channel

```bash
rails generate channel Chat
```

Generates:

```ruby
# app/channels/chat_channel.rb
class ChatChannel < ApplicationCable::Channel
  def subscribed
    # Called when consumer subscribes
    stream_from "chat_#{params[:room_id]}"
  end

  def unsubscribed
    # Called when consumer unsubscribes (cleanup)
  end

  def speak(data)
    # Called when consumer sends message
    Message.create!(
      content: data['message'],
      user: current_user,
      room_id: params[:room_id]
    )
  end
end
```

```javascript
// app/javascript/channels/chat_channel.js
import consumer from "./consumer"

consumer.subscriptions.create(
  { channel: "ChatChannel", room_id: 123 },
  {
    connected() {
      console.log("Connected to chat")
    },

    disconnected() {
      console.log("Disconnected from chat")
    },

    received(data) {
      // Handle broadcasted message
      const messagesContainer = document.getElementById("messages")
      messagesContainer.insertAdjacentHTML("beforeend", data.html)
    },

    speak(message) {
      this.perform("speak", { message: message })
    }
  }
)
```

### Streaming

Subscribe to broadcasts:

```ruby
class ChatChannel < ApplicationCable::Channel
  def subscribed
    # Stream from named channel
    stream_from "chat_room_#{params[:room_id]}"

    # Stream for current user only
    stream_for current_user

    # Stop streaming
    stop_all_streams
  end
end
```

### Channel Callbacks

Channels support lifecycle callbacks and exception handling:

```ruby
class ChatChannel < ApplicationCable::Channel
  before_subscribe :verify_access
  after_subscribe :log_subscription

  rescue_from UnauthorizedError, with: :handle_unauthorized

  def subscribed
    stream_from "chat_#{params[:room_id]}"
  end

  private

  def verify_access
    reject unless current_user.can_access?(params[:room_id])
  end

  def log_subscription
    Rails.logger.info "User #{current_user.id} subscribed to chat"
  end

  def handle_unauthorized(exception)
    # Handle error, optionally broadcast error message
    transmit(error: "Unauthorized access")
  end
end
```

Available callbacks: `before_subscribe`, `after_subscribe`, `before_unsubscribe`, `after_unsubscribe`.

## Broadcasting

Send messages to channel subscribers:

### From Models

```ruby
class Message < ApplicationRecord
  belongs_to :room
  belongs_to :user

  after_create_commit :broadcast_message

  private

  def broadcast_message
    ActionCable.server.broadcast(
      "chat_room_#{room_id}",
      {
        html: ApplicationController.render(
          partial: 'messages/message',
          locals: { message: self }
        ),
        user: user.name
      }
    )
  end
end
```

### From Controllers

```ruby
class MessagesController < ApplicationController
  def create
    @message = Message.new(message_params)

    if @message.save
      # Broadcast happens in model callback
      head :ok
    else
      render json: { errors: @message.errors }, status: :unprocessable_entity
    end
  end
end
```

### From Jobs

```ruby
class NotificationBroadcastJob < ApplicationJob
  queue_as :default

  def perform(notification)
    ActionCable.server.broadcast(
      "notifications_#{notification.user_id}",
      { html: render_notification(notification) }
    )
  end

  private

  def render_notification(notification)
    ApplicationController.render(
      partial: 'notifications/notification',
      locals: { notification: notification }
    )
  end
end
```

## Authentication

Authenticate WebSocket connections:

```ruby
# 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 verified_user = User.find_by(id: cookies.encrypted[:user_id])
        verified_user
      else
        reject_unauthorized_connection
      end
    end
  end
end
```

Now `current_user` is available in all channels.

## Rails 8: Solid Cable

Solid Cable replaces Redis with database-backed pub/sub.

### Configuration

```yaml
# config/cable.yml
production:
  adapter: solid_cable
  polling_interval: 0.1  # 100ms
  message_retention: 1.day
```

```ruby
# No Redis needed!
# Solid Cable stores messages in database
# Polls for new messages every 100ms
```

### Migration

```bash
rails solid_cable:install
rails db:migrate
```

Creates `solid_cable_messages` table.

### Trade-offs

**Solid Cable:**
- Simpler deployment (no Redis)
- One database to manage
- ~100-150ms latency
- Sufficient for chat, notifications, updates

**Redis:**
- Lower latency (<50ms)
- Higher throughput
- Better for millions of connections

For most apps, Solid Cable is simpler and sufficient.

See `references/solid-cable.md` for details.

## Common Patterns

### Chat Application

```ruby
# Channel
class ChatChannel < ApplicationCable::Channel
  def subscribed
    stream_from "chat_#{params[:room_id]}"
  end

  def speak(data)
    Message.create!(
      room_id: params[:room_id],
      user: current_user,
      content: data['message']
    )
  end
end

# Model
class Message < ApplicationRecord
  after_create_commit -> {
    broadcast_append_to "chat_#{room_id}",
      target: "messages",
      partial: "messages/message",
      locals: { message: self }
  }
end
```

### Live Notifications

```ruby
class NotificationChannel < ApplicationCable::Channel
  def subscribed
    stream_for current_user
  end
end

# Broadcast to specific user
NotificationChannel.broadcast_to(user, {
  html: render_notification(notification)
})
```

### Presence (Who's Online)

```ruby
class AppearanceChannel < ApplicationCable::Channel
  def subscribed
    stream_from "appearances"
    broadcast_appearance("online")
  end

  def unsubscribed
    broadcast_appearance("offline")
  end

  def appear
    broadcast_appearance("online")
  end

  def away
    broadcast_appearance("away")
  end

  private

  def broadcast_appearance(status)
    ActionCable.server.broadcast("appearances", {
      user_id: current_user.id,
      username: current_user.name,
      status: status
    })
  end
end
```

See `references/action-cable-patterns.md` for more examples.

## Testing

### Channel Tests

```ruby
require "test_helper"

class ChatChannelTest < ActionCable::Channel::TestCase
  test "subscribes to stream" do
    subscribe room_id: 42

    assert subscription.confirmed?
    assert_has_stream "chat_42"
  end

  test "receives broadcasts" do
    subscribe room_id: 42

    perform :speak, message: "Hello!"

    assert_broadcast_on("chat_42", message: "Hello!")
  end
end
```

### Integration Tests

```ruby
test "broadcasts message to chat" do
  room = rooms(:general)

  assert_broadcasts("chat_#{room.id}", 1) do
    Message.create!(room: room, user: users(:alice), content: "Hello!")
  end
end
```

## Deployment Considerations

### Standalone Server

For high-traffic apps, run Action Cable on separate servers:

```ruby
# config/cable.yml
production:
  adapter: solid_cable
  url: wss://cable.example.com
```

### Scaling

Action Cable scales horizontally:
- Multiple app servers
- Shared pub/sub (Solid Cable database or Redis)
- Load balancer with WebSocket support

### Monitoring

Track connection count, message throughput, latency, and errors.

## Alternatives to Action Cable

### Server-Sent Events (SSE)

One-way server → client:

```ruby
def stream
  response.headers['Content-Type'] = 'text/event-stream'
  response.headers['Cache-Control'] = 'no-cache'

  sse = SSE.new(response.stream)
  sse.write({ message: "Hello" })
ensure
  sse.close
end
```

**Use when:** Only server → client needed (notifications, live feeds)

### Polling

Regular HTTP requests:

```javascript
setInterval(() => {
  fetch('/api/notifications/latest')
    .then(r => r.json())
    .then(data => updateUI(data))
}, 5000)
```

**Use when:** Simple updates, low frequency, broad browser support needed

## Further Reading

For deeper exploration:

- **`references/action-cable-patterns.md`**: Chat, notifications, presence patterns
- **`references/solid-cable.md`**: Database-backed pub/sub in Rails 8

For code examples (in `examples/`):

- **`chat-channel.rb`**: Real-time chat with typing indicators
- **`notifications-channel.rb`**: User-specific push notifications
- **`presence-channel.rb`**: Online status tracking
- **`dashboard-channel.rb`**: Admin dashboard with live stats
- **`multi-room-chat.rb`**: Multiple rooms with private messages
- **`collaborative-editing.rb`**: Document editing with cursors
- **`live-feed.rb`**: Real-time feed updates

## Summary

Action Cable provides:
- **WebSocket integration** with Rails
- **Channels** for logical grouping
- **Broadcasting** to connected clients
- **Authentication** via connection identification
- **Solid Cable** for database-backed pub/sub (Rails 8)
- **Turbo Streams** integration for HTML updates

Master Action Cable and you'll build real-time features that feel magical.

Related Skills

add-reaction

16
from diegosouzapw/awesome-omni-skill

Slack メッセージにリアクションを追加する。「リアクション追加」「リアクションつけて」「👍つけて」「絵文字で反応」「リアクションで返信」「いいねして」「リアクション送って」などで起動。User Token があればユーザーとしてリアクション、なければ Bot としてリアクション。

actions-pattern

16
from diegosouzapw/awesome-omni-skill

Garante que novas Actions sigam o padrão de classes actions reutilizáveis do Easy Budget.

actionbook

16
from diegosouzapw/awesome-omni-skill

This skill should be used when the user needs to automate multi-step website tasks. Activates for browser automation, web scraping, UI testing, or building AI agents. Provides complete action manuals with step-by-step instructions and verified selectors.

actionable-review-format-standards

16
from diegosouzapw/awesome-omni-skill

Standardized output format for code reviews with severity labels, file:line references, and fix code snippets. Use when generating review reports that need consistent, actionable feedback structure.

action-policy-coder

16
from diegosouzapw/awesome-omni-skill

Use proactively for authorization with ActionPolicy. Creates policies, scopes, and integrates with GraphQL/ActionCable. Preferred over Pundit for composable, cacheable authorization.

Action Pattern Conventions

16
from diegosouzapw/awesome-omni-skill

This skill should be used when the user asks about "Laravel action pattern", "action class naming", "how to structure actions", "React component patterns", "Node.js service structure", "framework-specific conventions", or discusses creating reusable, focused classes following action pattern conventions in Laravel, Symfony, React, Vue, or Node.js projects.

action-mapping-designer

16
from diegosouzapw/awesome-omni-skill

This skill should be used when ensuring training focuses on performance outcomes and business impact. Use this skill to identify essential content, design performance-focused activities, create job aids, and eliminate unnecessary training.

action-item-organizer

16
from diegosouzapw/awesome-omni-skill

Systematic framework for extracting actionable items from documents and organizing them into prioritized, trackable checklists. Use when converting reports, meeting notes, audits, or any document with embedded action items into structured TODO lists.

action-creator

16
from diegosouzapw/awesome-omni-skill

Creates user-specific one-click action templates that execute email operations when clicked in the chat interface. Use when user wants reusable actions for their specific workflows (send payment reminder to ACME Corp, forward bugs to engineering, archive old newsletters from specific sources).

Action Cable & WebSocket Patterns

16
from diegosouzapw/awesome-omni-skill

Real-time WebSocket features with Action Cable in Rails. Use when: (1) Building real-time chat, (2) Live notifications/presence, (3) Broadcasting model updates, (4) WebSocket authorization. Trigger keywords: Action Cable, WebSocket, real-time, channels, broadcasting, stream, subscriptions, presence, cable

action-builder-skill

16
from diegosouzapw/awesome-omni-skill

Use when creating or refactoring Nango integration actions to be thin API wrappers - provides patterns for minimal transformation logic, direct proxy calls, and standardized structure

acc-create-action

16
from diegosouzapw/awesome-omni-skill

Generates ADR Action classes for PHP 8.5. Creates single-responsibility HTTP endpoint handlers with PSR-7 support. Includes unit tests.