# Action Cable

> Setup and use ActionCable for real-time features in Rails applications using WebSockets. Use when implementing real-time updates, live notifications, broadcasting changes, or when the user mentions WebSockets, ActionCable, channels, broadcasting, or Turbo Streams over cable.

- Skill: `rolemodel/action-cable` (Agent Skill)
- Install (CLI): `npx skillmds@latest add rolemodel/action-cable`
- Raw SKILL.md: https://api.skillmd.com/api/skills/rolemodel/action-cable/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: rolemodel (https://skillmd.com/u/rolemodel)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/rolemodel/action-cable

---


# ActionCable 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.

```ruby
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.

```ruby
module ApplicationCable
  class Channel < ActionCable::Channel::Base
  end
end
```

### 3. JavaScript Setup (`app/javascript/initializers/actioncable.js`)

Initialize ActionCable consumer on the client side.

```javascript
import * as ActionCable from '@rails/actioncable'

ActionCable.logger.enabled = false
```

## Broadcasting Updates

### With Turbo Streams (recommended)

Subscribe to a stream in views:

```slim
= turbo_stream_from record
= turbo_stream_from [record, "channel_name"]
```

Broadcast Turbo Stream updates from controllers or background jobs:

```ruby
# 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:
```slim
= turbo_stream_from current_organization, "timers"

#notifications
```

Controller:
```ruby
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`)

```yaml
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`:

```ruby
Rails.application.routes.draw do
  mount ActionCable.server => '/cable'
end
```

## Debugging

Enable logging in development:

```javascript
// app/javascript/initializers/actioncable.js
ActionCable.logger.enabled = true
```

Check connection status:

```javascript
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_for` instead of `stream_from` when possible for automatic scoping
- Never trust client-side data without validation
- Consider rate limiting for channels that accept client messages

