You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails 6 API使用ActionCable报Subscription class not found错误

运行环境
  • Ruby 版本:ruby 3.0.2p107
  • Rails 版本:Rails 6.1.6
  • 技术栈:Rails 作为 API 后端,React TypeScript 作为前端
问题复现代码

后端代码

app/channels/notification_channel.rb

class NotificationChannel < ApplicationCable::Channel
  def subscribed
    stream_from "notification_channel_#{current_user.user_id}"
  end

  def unsubscribed; 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_user
    end

    private 

    def find_user
      current_user = Profile::Account.find_by(user_id: request.query_parameters[:user_id])
      current_user ? current_user : reject_unauthorized_connection
    end
  end
end

前端代码

const createSubscription = (consumer: ActionCable.Cable) => {
    consumer.subscriptions.create({ channel: `notification_channel_${user.sub}` }, {
        connected: () => console.log(`connected to notifications.${user.sub}`),
        received: (notification) => handleReceivedNotification(notification),
    });
};

const handleReceivedNotification = (notification: any) => {
    console.log(JSON.stringify(notification));
}

useEffect((): void => {
    if (user) setComsumer(ActionCable.createConsumer(`ws://localhost:3100/cable?user_id=${user.sub}`));
}, [user]);

useEffect((): void => {
    if (consumer) createSubscription(consumer);
}, [consumer]);
异常表现

启动服务后WebSocket连接可以正常建立,但存在以下问题:

  • 服务端日志抛出订阅类找不到的错误:
Registered connection (Z2lkOi8vYXBpL1Byb2ZpbGU6OkFjY291bnQvMQ)
Subscription class not found: "notification_channel_facebook|10157537128720479"
  • 控制台执行广播操作返回0,消息无法推送到前端:
$ ActionCable.server.broadcast "notification_channel_#{user.user_id}", { action: "new_notification" }
D, [2022-07-07T14:44:03.820530 #19220] DEBUG -- : [ActionCable] Broadcasting to notification_channel_facebook|10157537128720479: {:action=>"new_notification"}
=> 0
  • Redis pubsub频道列表中无notification_channel相关频道:
Redis.new.pubsub("channels")
=> ["action_cable/Z2lkOi8vYXBpL1Byb2ZpbGU6OkFjY291bnQvMQ", "_action_cable_internal"]
相关配置

config/cable.yml

default: &default
  adapter: redis
  url: redis://localhost:6379/1

development:
  <<: *default

test:
  <<: *default

production:
  adapter: redis
  url: <%= ENV['REDIS_URL'] %>
  channel_prefix: api_production

config/application.rb

require "rails"
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "active_storage/engine"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "action_cable/engine"
# require "sprockets/railtie"
require "rails/test_unit/railtie"
require "active_storage/engine"
require "action_mailbox/engine"
问题根因

ActionCable客户端创建订阅时,传入的channel参数必须和后端定义的Channel类名(驼峰格式)完全匹配,服务端会根据这个参数路由到对应的Channel类处理订阅请求。
当前前端代码错误地将流名称notification_channel_${user.sub}作为channel参数传递,服务端收到请求后会尝试查找名为notification_channel_facebook|10157537128720479的Channel类,自然匹配失败抛出Subscription class not found错误。
由于Channel类匹配失败,NotificationChannel的subscribed方法不会执行,stream_from逻辑未触发,客户端没有订阅对应的广播流,因此广播时返回0(无订阅者),Redis中也看不到对应的频道。

修复方案
  1. 修改前端订阅创建逻辑,channel固定传入后端类名NotificationChannel,用户ID作为自定义参数传递:
const createSubscription = (consumer: ActionCable.Cable) => {
    consumer.subscriptions.create(
        {
            channel: "NotificationChannel",
            user_id: user.sub
        },
        {
            connected: () => console.log(`connected to notifications.${user.sub}`),
            received: (notification) => handleReceivedNotification(notification),
        }
    );
};
  1. (可选优化)调整后端subscribed方法,从订阅参数中获取用户ID拼接流名称,和前端传参保持一致:
class NotificationChannel < ApplicationCable::Channel
  def subscribed
    stream_from "notification_channel_#{params[:user_id]}"
  end

  def unsubscribed; end
end

修复后重启Rails服务,重新建立WebSocket连接即可正常订阅、接收广播消息。


内容的提问来源于stack exchange,提问作者Andrea Reginato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 18:18:26