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

Rails6部署Heroku触发Stimulus Reflex报ActionCable连接未打开错误如何解决

报错核心原因

ActionCable 的 WebSocket 连接在用户触发 Stimulus Reflex 操作时还未完成初始化,或 Heroku 生产环境的 ActionCable 配置存在限制导致连接未正常建立。

解决步骤

1. 前端优化触发逻辑,等待连接建立后再开放交互

新增 Stimulus 控制器控制单选按钮的可用状态,避免连接未就绪时触发操作:
在 app/javascript/controllers/preps_controller.js 中添加以下代码:

import { Controller } from "@hotwired/stimulus"
import StimulusReflex from 'stimulus_reflex'

export default class extends Controller {
  connect() {
    StimulusReflex.register(this)
    if (this.isActionCableConnectionOpen()) {
      this.enableRadios()
    } else {
      document.addEventListener('cable:connected', () => this.enableRadios())
    }
  }

  enableRadios() {
    this.element.querySelectorAll('input[type=radio]').forEach(radio => {
      radio.disabled = false
    })
  }

  togglePrep() {
    if (this.isActionCableConnectionOpen()) {
      this.stimulate('PrepsReflex#toggle_prep', event.target)
    }
  }
}

修改 more_info.html.erb 模板,绑定控制器并初始禁用单选按钮:

<div class='preps' data-controller="preps">
  <%= f.input :heads_prep,  
    label_html: {class:"label"}, 
    item_wrapper_class: "radio-label", 
    input_html: {
      disabled: true,
      data: {
        action: "change->preps#togglePrep", 
        prepValue: 'heads', 
        activity: @activity.id
      }
    },  
    collection: Activity.heb_preps.map{ |k, v| [v, k] }, 
    as: :radio_buttons 
  %>
  <%= f.input :guides_prep, 
    label_html: {class:"label"}, 
    item_wrapper_class: "radio-label", 
    input_html: {
      disabled: true,
      data: {
        action: "change->preps#togglePrep", 
        prepValue: 'guides', 
        activity: @activity.id
      }
    }, 
    collection: Activity.heb_preps.map{ |k, v| [v, k] }, 
    as: :radio_buttons 
  %>
</div>

2. 修复 Heroku 生产环境 ActionCable 配置

修改 config/environments/production.rb,添加 WebSocket 相关配置:

# 允许WebSocket跨域请求
config.action_cable.allowed_request_origins = [/https:\/\/.*\.herokuapp\.com/]
# 配置ActionCable服务地址,APP_DOMAIN替换为你的Heroku应用域名
config.action_cable.url = "wss://#{ENV['APP_DOMAIN']}/cable"

检查 config/routes.rb 确认已挂载 ActionCable:

Rails.application.routes.draw do
  # 其他路由保持不变
  mount ActionCable.server => '/cable'
end

在 Heroku 后台的配置变量中添加 APP_DOMAIN,值为你的应用域名,格式如 xxx.herokuapp.com。

3. 后端 Reflex 代码优化(可选)

添加空值安全调用,避免销毁不存在的 Mifal 记录时报错:

# frozen_string_literal: true

class PrepsReflex < ApplicationReflex
  delegate :current_user, to: :connection

  def toggle_prep
    activity = Activity.find(element.dataset.activity)
    prep = element.dataset.prepvalue
    if element.value == 'yes'
      activity.update("#{prep}_prep": :yes)
      activity.mifals.find_or_create_by(mifal_type: prep) do |mifal|
        mifal.name = "#{Mifal.heb_mifal_type(prep)} #{activity.name}"
      end
    else
      activity.update("#{prep}_prep": :no)
      activity.mifals.find_by(mifal_type: prep)&.destroy
    end
  end
end

内容的提问来源于stack exchange,提问作者Guy Natan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 06:24:00