ActionCable for real-time WebSocket communication

Sarah Mitchell Feb 2026
3 tabs
# app/channels/chat_channel.rb
class ChatChannel < ApplicationCable::Channel
  def subscribed
    # Subscribe to a specific room
    room = Room.find(params[:room_id])

    # Authorize user
    reject unless current_user.can_access?(room)

    stream_for room

    # Track user presence
    room.users << current_user unless room.users.include?(current_user)
    broadcast_user_joined(room)
  end

  def unsubscribed
    room = Room.find(params[:room_id])
    room.users.delete(current_user)
    broadcast_user_left(room)
  end

  def receive(data)
    # Receive message from client
    room = Room.find(params[:room_id])
    message = room.messages.create!(
      user: current_user,
      content: data['message']
    )

    # Broadcast to all subscribed clients
    ChatChannel.broadcast_to(room, {
      type: 'message',
      message: MessageSerializer.new(message).as_json,
      user: UserSerializer.new(current_user).as_json
    })
  end

  def typing(data)
    room = Room.find(params[:room_id])
    ChatChannel.broadcast_to(room, {
      type: 'typing',
      user_id: current_user.id,
      user_name: current_user.name
    })
  end

  private

  def broadcast_user_joined(room)
    ChatChannel.broadcast_to(room, {
      type: 'user_joined',
      user: UserSerializer.new(current_user).as_json,
      users_count: room.users.count
    })
  end

  def broadcast_user_left(room)
    ChatChannel.broadcast_to(room, {
      type: 'user_left',
      user_id: current_user.id,
      users_count: room.users.count
    })
  end
end

# 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
3 files · ruby, javascript Explain with highlit

ActionCable integrates WebSockets seamlessly with Rails. Channels handle pub/sub messaging between server and clients. I use ActionCable for chat, notifications, live updates. Channels subscribe clients to streams; broadcasting pushes data to subscribed clients. Connection authorization ensures only authenticated users connect. Channel callbacks—subscribed, unsubscribed, receive—handle lifecycle events. Streaming from models broadcasts ActiveRecord changes automatically. ActionCable scales with Redis for multi-server deployments. Testing channels uses connectionstub and subscriptionstub. Understanding ActionCable's relationship with Turbo Streams unlocks powerful real-time Rails UIs. ActionCable brings WebSocket simplicity to Rails without external services.