20

I'm trying to create a simple chat-like application (planning poker app) with Action Cable. I'm a little bit confused by the terminology, files hierarchy and how the callbacks work.

This is the action that creates user session:

class SessionsController < ApplicationController
  def create
    cookies.signed[:username] = params[:session][:username]
    redirect_to votes_path
  end
end

A user can then post a vote that should be broadcasted to everyone:

class VotesController < ApplicationController
  def create
    ActionCable.server.broadcast 'poker',
                                 vote: params[:vote][:body],
                                 username: cookies.signed[:username]
    head :ok
  end
end

Up to this point everything is clear for me and works fine. The problem is - how do I display the number of connected users? Is there a callback that fires in JS when a user (consumer?) connects? What I want is when I open 3 tabs in 3 different browsers in incognito mode I would like to display "3". When a new user connects, I would like the number to increment. If any user disconnects, the number should decrement.

My PokerChannel:

class PokerChannel < ApplicationCable::Channel
  def subscribed
    stream_from 'poker'
  end
end

app/assets/javascripts/poker.coffee:

App.poker = App.cable.subscriptions.create 'PokerChannel',

  received: (data) ->
    $('#votes').append @renderMessage(data)

  renderMessage: (data) ->
    "<p><b>[#{data.username}]:</b> #{data.vote}</p>"
4

5 回答 5

19

似乎一种方法是使用

ActionCable.server.connections.length

(请参阅评论中的警告)

于 2015-10-05T10:06:40.413 回答
3

对于快速(可能并不理想)的解决方案,您可以编写一个跟踪订阅计数的模块(使用 Redis 存储数据):

#app/lib/subscriber_tracker.rb
module SubscriberTracker
  #add a subscriber to a Chat rooms channel 
  def self.add_sub(room)
    count = sub_count(room)
    $redis.set(room, count + 1)
  end

  def self.remove_sub(room)
    count = sub_count(room)
    if count == 1
      $redis.del(room)
    else
      $redis.set(room, count - 1)
    end
  end

  def self.sub_count(room)
    $redis.get(room).to_i
  end
end

并在频道类中更新您订阅和取消订阅的方法:

class ChatRoomsChannel < ApplicationCable::Channel  
  def subscribed
     SubscriberTracker.add_sub params['room_id']
  end

  def unsubscribed
     SubscriberTracker.remove_sub params['chat_room_id'] 
  end
end
于 2017-02-17T08:45:52.697 回答
3

在有关who is connected 的相关问题中,使用 redis 的人有一个答案:

Redis.new.pubsub("channels", "action_cable/*")

如果您只想要连接数:

Redis.new.pubsub("NUMPAT", "action_cable/*")

这将汇总来自所有服务器的连接。

RemoteConnections 类和 InternalChannel 模块中涵盖的所有魔法。

TL;DR 以 action_cable/* 为前缀的特殊通道上订阅的所有连接,仅用于断开套接字与主轨道应用程序的连接。

于 2017-12-01T14:23:48.667 回答
0

我想我为你找到了答案。尝试这个:

ActionCable.server.connections.select { |con| con.current_room == room }.length?

我可以在我的代码中的任何地方使用它,并检查所选流的连接用户数量:)

在我的connection.rb我有这样的事情:

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

    def connect
      self.current_room = find_room
    end

    private

    def find_room
      .....
    end
  end
end

希望对任何人都有帮助。

于 2021-05-07T14:18:07.527 回答
-1

ActionCable.server.pubsub.send(:listener).instance_variable_get("@subscribers")

您可以在将在广播中执行的程序的键和数组中获取带有订阅标识符的地图。所有过程都接受消息作为参数并具有记忆连接。

于 2018-10-16T14:49:05.567 回答