or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

connection-management.mdindex.mdjavascript-client.mdrails-integration.mdserver-broadcasting.mdsubscription-adapters.md
tile.json

rails-integration.mddocs/

Rails Integration

ActionCable provides seamless Rails integration through its engine, helpers, generators, and configuration system. This enables developers to easily add real-time features to Rails applications using familiar conventions.

Capabilities

ActionCable Engine

Rails engine that automatically configures ActionCable within Rails applications.

class ActionCable::Engine < Rails::Engine
  # Engine configuration
  config.action_cable = ActiveSupport::OrderedOptions.new
  config.action_cable.mount_path = ActionCable::INTERNAL[:default_mount_path]
  config.eager_load_namespaces << ActionCable
end

The engine automatically:

  • Mounts ActionCable server at configured path (default: /cable)
  • Includes ActionCable helpers in ActionView
  • Sets up logger integration
  • Configures connection class resolution
  • Sets up executor callbacks for channels and workers

Rails Helpers

View helpers for integrating ActionCable with Rails applications.

module ActionCable::Helpers::ActionCableHelper
  # Generate meta tag with ActionCable URL for JavaScript client
  # @return [String] HTML meta tag with action-cable-url
  def action_cable_meta_tag
    tag "meta", name: "action-cable-url", content: (
      ActionCable.server.config.url ||
      ActionCable.server.config.mount_path ||
      raise("No Action Cable URL configured")
    )
  end
end

Usage Examples:

<!-- In Rails layout file -->
<head>
  <%= action_cable_meta_tag %>
  <%= javascript_include_tag 'application' %>
</head>

<!-- Generates -->
<meta name="action-cable-url" content="/cable" />

<!-- Or with custom URL -->
<meta name="action-cable-url" content="ws://cable.example.com" />

Channel Generator

Rails generator for creating ActionCable channels with boilerplate code.

class Rails::Generators::ChannelGenerator < NamedBase
  # Generate channel file and related assets
  def create_channel_file
  end
  
  # Command line arguments
  argument :actions, type: :array, default: [], banner: "method method"
  
  # Options
  class_option :assets, type: :boolean
end

Usage Examples:

# Generate basic channel
rails generate channel Chat

# Generate channel with actions
rails generate channel Chat speak typing

# Generate channel with JavaScript assets
rails generate channel Chat speak --assets

Generated files:

  • app/channels/chat_channel.rb - Server-side channel class
  • app/assets/javascripts/channels/chat.js - Client-side JavaScript (if --assets)
  • app/channels/application_cable/ - Base connection and channel classes

Generated Channel Structure

The generator creates channels with this structure:

# app/channels/chat_channel.rb
class ChatChannel < ApplicationCable::Channel
  def subscribed
    # stream_from "some_channel"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end

  def speak(data)
    # Handle the speak action
  end

  def typing(data)
    # Handle the typing action  
  end
end

Application Cable Base Classes

Generated base classes for connection and channel:

# app/channels/application_cable/connection.rb
module ApplicationCable
  class Connection < ActionCable::Connection::Base
    # Connection authentication and identification logic
  end
end

# app/channels/application_cable/channel.rb  
module ApplicationCable
  class Channel < ActionCable::Channel::Base
    # Shared channel functionality
  end
end

Configuration

Server Configuration

Configure ActionCable server settings in Rails applications.

class ActionCable::Server::Configuration
  # Server URL for WebSocket connections
  attr_accessor :url
  
  # Mount path for ActionCable server (default: "/cable")
  attr_accessor :mount_path
  
  # Allowed request origins for CORS
  attr_accessor :allowed_request_origins
  
  # Connection class resolver
  attr_accessor :connection_class
  
  # Worker pool size
  attr_accessor :worker_pool_size
  
  # Logger instance
  attr_accessor :logger
  
  # Subscription adapter configuration
  attr_accessor :cable
  
  # Pubsub adapter class
  attr_accessor :pubsub_adapter
end

Configuration Examples:

# config/environments/production.rb
Rails.application.configure do
  # Configure ActionCable server URL
  config.action_cable.url = 'wss://cable.example.com'
  
  # Or use mount path for same-origin connections
  config.action_cable.mount_path = '/cable'
  
  # Configure allowed origins
  config.action_cable.allowed_request_origins = [
    'https://example.com',
    /https:\/\/.*\.example\.com/
  ]
  
  # Set worker pool size
  config.action_cable.worker_pool_size = 10
end

# config/environments/development.rb
Rails.application.configure do
  # Development allows localhost origins automatically
  config.action_cable.mount_path = '/cable'
end

Cable Configuration

Configure subscription adapters via config/cable.yml:

# config/cable.yml
development:
  adapter: async

test:
  adapter: test

production:
  adapter: redis
  url: redis://localhost:6379/1
  channel_prefix: myapp_production

Adapter-specific configuration:

# Redis configuration
production:
  adapter: redis
  url: redis://user:password@redis.example.com:6380/0
  channel_prefix: myapp_production
  timeout: 1
  reconnect_attempts: 3

# PostgreSQL configuration  
production:
  adapter: postgresql
  url: postgresql://user:password@localhost/myapp_production
  channel_prefix: myapp_production

# Multiple Redis instances
production:
  adapter: redis
  url: 
    - redis://redis1.example.com:6379/0
    - redis://redis2.example.com:6379/0
  channel_prefix: myapp_production

Connection Class Configuration

Configure custom connection classes:

# config/application.rb
module MyApp
  class Application < Rails::Application
    # Specify custom connection class
    config.action_cable.connection_class = -> { "MyConnection".constantize }
    
    # Or use lambda for lazy loading
    config.action_cable.connection_class = -> { 
      "ApplicationCable::Connection".safe_constantize || ActionCable::Connection::Base 
    }
  end
end

Routing Integration

Automatic Route Mounting

ActionCable automatically mounts routes when configured:

# Routes are automatically added by the engine
# Equivalent to:
Rails.application.routes.draw do
  mount ActionCable.server => '/cable', internal: true
end

Custom Route Mounting

# config/routes.rb
Rails.application.routes.draw do
  # Mount at custom path
  mount ActionCable.server => '/websocket'
  
  # Or disable automatic mounting and mount manually
  # config.action_cable.mount_path = nil
  mount ActionCable.server => '/custom/cable/path'
end

Deployment Integration

Puma Integration

Configure Puma server for ActionCable:

# config/puma.rb
workers ENV.fetch("WEB_CONCURRENCY") { 2 }
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
threads threads_count, threads_count

# Preload application for ActionCable
preload_app!

# Allow puma to be restarted by `rails restart` command
plugin :tmp_restart

# ActionCable configuration
if ENV['RAILS_ENV'] == 'production'
  # Bind to specific interface for ActionCable
  bind 'tcp://0.0.0.0:3000'
end

Nginx Configuration

Configure Nginx for ActionCable WebSocket proxying:

# nginx.conf
upstream cable {
  server 127.0.0.1:3000;
}

server {
  listen 80;
  server_name example.com;
  
  location /cable {
    proxy_pass http://cable;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }
}

Capistrano Integration

Deploy ActionCable with Capistrano:

# config/deploy.rb
set :application, 'myapp'
set :repo_url, 'git@github.com:user/myapp.git'

# Restart ActionCable server after deployment
after 'deploy:restart', 'actioncable:restart'

namespace :actioncable do
  task :restart do
    on roles(:app) do
      execute :touch, release_path.join('tmp/restart.txt')
    end
  end
end

Testing Integration

ActionCable Test Helpers

Rails provides test helpers for ActionCable:

# Test helper methods available in Rails tests
class ActionCable::TestHelper
  # Assert that a broadcast was made
  def assert_broadcasts(stream, number)
  end
  
  # Assert no broadcasts were made
  def assert_no_broadcasts(stream)
  end
  
  # Capture broadcasts during block execution
  def capture_broadcasts(stream, &block)
  end
end

Testing Examples:

# test/channels/chat_channel_test.rb
class ChatChannelTest < ActionCable::Channel::TestCase
  test "subscribes to stream" do
    subscribe room_id: 1
    
    assert subscription.confirmed?
    assert_has_stream "chat_1"
  end
  
  test "speaks and broadcasts" do
    subscribe room_id: 1
    
    assert_broadcasts "chat_1", 1 do
      perform :speak, message: "Hello"
    end
  end
end

# Integration test
class ChatSystemTest < ActionDispatch::SystemTestCase
  test "real time messaging" do
    visit chat_room_path(1)
    
    assert_broadcasts "chat_1", 1 do
      fill_in "message", with: "Hello everyone"
      click_button "Send"
    end
    
    assert_selector ".message", text: "Hello everyone"
  end
end

Test Adapter

Configure test adapter for testing:

# config/cable.yml
test:
  adapter: test

# Or inline adapter for immediate execution
test:
  adapter: inline