操作电缆:如何在客户取消订阅时获取客户的订阅名称?

时间:2017-04-21 09:08:03

标签: ruby-on-rails actioncable

我正在使用Devise和gem' devise_token_auth'在Rails 5 API Action Cable中实现聊天。

我有ChatRequestChannel参与订阅:

stream_from "chat_request_#{chat_request_chanel_token}_channel"

我需要以某种方式可靠地检索chat_request_chanel_token挂钩内的unsubscribed值 - 向其他订阅者发送消息。这是我的代码:

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\":\"client1@example.com\"}"}

当客户端与Action Cable断开连接时,实际上会调用unsubscribed挂钩。因此,我无法向unsubscribed提供任何参数。

我建议每个客户端只有一个(每个参数)参数化订阅ChatRequestChannel。它是存储在Action Cable中的某个位置并且可以检索吗?

1 个答案:

答案 0 :(得分:0)

我可能找到了。

中有一个数组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挂钩。在stream_name内呼叫unsubscribe会返回当前正在停止的订阅的名称,允许您通知此频道的所有其他订阅者:

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