Action Cable:客户端取消订阅时如何获取客户端的订阅名称?

问题描述:

我正在使用Devise和gem'devise_token_auth'在Rails 5 API Action Cable中实现聊天功能。Action Cable:客户端取消订阅时如何获取客户端的订阅名称?

我有一个参数化订阅一个ChatRequestChannel

stream_from "chat_request_#{chat_request_chanel_token}_channel"

我需要以某种可靠的检索unsubscribed钩内chat_request_chanel_token值 - 将消息发送给其他用户。这里是我的代码:

class ChatRequestChannel < ApplicationCable::Channel 
    def subscribed 

    answerer = params["answerer"] 

    chat_request_chanel_token = answerer 

    answerer_user = User.find_by email: answerer 

    if answerer_user 

     stream_from "chat_request_#{chat_request_chanel_token}_channel" 

    else 
# http://api.rubyonrails.org/classes/ActionCable/Channel/Base.html#class-ActionCable::Channel::Base-label-Rejecting+subscription+requests 
     reject 

    end 

    end 

    def unsubscribed 
    # Any cleanup needed when channel is unsubscribed 

     chat_request_chanel_token = "What to put here????" 

     message = "Client disconnected" 

     ActionCable.server.broadcast "chat_request_#{chat_request_chanel_token}_channel", 
            disconnected: message 

    end 
end 

所有客户端订阅ChatRequestChannel,并通过这样的命令(answerer PARAM从客户端变化到客户端):

{"command":"subscribe","identifier":"{\"channel\":\"ChatRequestChannel\",\"answerer\":\"[email protected]\"}"} 

unsubscribed钩实际上被调用时,客户端断开连接来自Action Cable。所以我不能提供任何参数unsubscribed

我建议每个客户端应该只有一个(每个参数)参数化订阅ChatRequestChannel。它是否存储在Action Cable内的某个地方,可以被检索?

我大概找到了。里面有一个Array streams

/var/lib/gems/2.3.0/gems/actioncable-5.0.1/lib/action_cable/channel/streams.rb

def stream_from(broadcasting, callback = nil, coder: nil, &block) 
     broadcasting = String(broadcasting) 

     # Don't send the confirmation until pubsub#subscribe is successful 
     defer_subscription_confirmation! 

     # Build a stream handler by wrapping the user-provided callback with 
     # a decoder or defaulting to a JSON-decoding retransmitter. 
     handler = worker_pool_stream_handler(broadcasting, callback || block, coder: coder) 
     streams << [ broadcasting, handler ] 

     connection.server.event_loop.post do 
      pubsub.subscribe(broadcasting, handler, lambda do 
      ensure_confirmation_sent 
      logger.info "#{self.class.name} is streaming from #{broadcasting}" 
      end) 
     end 
     end 

见线streams << [ broadcasting, handler ]

下面是在此基础上我的代码:

module ApplicationCable 
    class Channel < ActionCable::Channel::Base 
    include ApplicationHelper 

     def stream_name 
     streams.try(:[],0).try(:[],0) 
     end 

     def token_from_stream_name 

     stream_name ? stream_name.gsub(channel_name,"").slice(1..-"_channel".size-1) : "" 

     end 
    end 
end 

stream_name方法现已可用内unsubscribe挂钩。当客户端从服务器套接字断开连接时,会自动为每个客户端订阅(到该通道)调用unsubscribed钩子。在unsubscribe之内调用stream_name返回当前正在停止的订阅的名称,以允许您通知此通道的所有其他订阅者:

class ChatChannel < ApplicationCable::Channel 
.... 
    def unsubscribed 
    # Any cleanup needed when channel is unsubscribed 

    message = { user_id: current_user.id, online: :off } 

    ActionCable.server.broadcast stream_name, chat_cancel: message  
    end 
.... 
end