helper_method 不适用于 ActionCable

Posted

技术标签:

【中文标题】helper_method 不适用于 ActionCable【英文标题】:helper_method not working with ActionCable 【发布时间】:2020-04-21 11:35:24 【问题描述】:

我是 Ruby on Rails 的新手,过去 2 个月我一直在尝试了解 ActionCable。

我在

中定义了一个辅助方法 :current_user

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  helper_method :current_user

  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end

end

当从

调用它时

app/views/layouts/application.html.erb

<%= current_user.id %>

它显示:例如 1。 但是,当我将 :current_user 带到 Action Cable 时,它​​显示为空或 nil

app/channels/application_cable/connection.rb

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user
      logger.add_tags "ActionCable", "User: #current_user.id"
    end

  end
end

终端: 成功升级到 WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket) 有一个异常 - NoMethodError(undefined method `id' for nil:NilClass)

在此先感谢您的帮助或指导。

【问题讨论】:

【参考方案1】:

如果您看到您提供的文档,您就会知道 identified_by 不是 Channel 实例的方法。它是 Actioncable::Connection 的一种方法。从 Rails 指南 Actioncable 概述中,Connection 类如下所示:

#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 current_user = User.find_by(id: cookies.signed[:user_id])
       current_user 
   else
       reject_unauthorized_connection 
   end 
  end
 end 
end

如您所见,current_user 在此处不可用。相反,您必须在此处创建一个 current_user 连接。 websocket 服务器没有会话,但它可以读取与主应用程序相同的 cookie。所以我想,您需要在身份验证后保存cookie。尽快谢谢..

【讨论】:

感谢大家的帮助和快速澄清@max【参考方案2】:

您的 ApplicationController(或一般的控制器)、助手和 ActionCable 之间没有关系。它们是完全不同的概念。

控制器响应常规的 HTTP 请求。它们继承自 ActionController::BaseActionController::ApiActionController::Metal

Helper 只是位于 app/helpers 目录中的模块,它们包含在视图上下文中。这是控制器提供视图的上下文。当您调用 helper_method :current_user 时,您也可以在控制器中使用该方法。

但 ActionCable 连接不是控制器。它也与控制器或 MVC 没有任何关系。

连接构成了客户端-服务器关系的基础。为了 服务器接受的每个 WebSocket,一个连接对象是 实例化。

Websockets 是一个完全独立于 HTTP 的协议。

虽然您可以将您的助手包含在 Connection 类中,因为它们只是模块,但它不会像 session middleware is not available in ActionCable 一样在这里为您提供帮助。因此,您根据一些教程构建的基于会话的小身份验证不可能神奇地开始在 ActionCable 中工作。

您仍然可以通过cookies.signed 访问 cookie,因此您需要修改您的身份验证系统,以便它设置一个签名的 HTTP cookie,然后您可以在 ActionCable 中读取该 cookie。

【讨论】:

【参考方案3】:

仅在您的视图中可用的辅助方法。记住这一点。

【讨论】:

以上是关于helper_method 不适用于 ActionCable的主要内容,如果未能解决你的问题,请参考以下文章

Facebook publish_action 权限不适用于发帖

Android- Intent.ACTION_CALL 不适用于以“911”开头的手机

带有 Intent.VIEW_ACTION 的 Android 安装 apk 不适用于文件提供程序

App Action 适用于 App Actions 测试工具,但不适用于 Google Assistant

Facebook publish_action权限不适用于发布

NGXS:测试分派的动作不适用于 ofActionDispatched