我有一个订阅用户的ActionCable方法。如果启动了新的convo,我也想要将用户订阅到新频道。我无法弄清楚在控制器中调用通道方法的正确语法。
更新:问题是消息在发送时会附加到聊天框中,但是当发送第一条消息时,尚未建立websocket连接,因此它会向用户查看消息是否未发送(因为它没有附加)。
信道/ msgs_channel.rb
class MsgsChannel < ApplicationCable::Channel
#This function subscribes the user to all existing convos
def subscribed
@convos = Convo.where("sender_id = ? OR recipient_id = ?", current_user, current_user)
@convos.each do |convo|
stream_from "msg_channel_#{convo.id}"
end
end
#This is a new function I wrote to subscribe the user to a new convo that is started during their session.
def subscribe(convo_id)
stream_from "msg_channel_#{convo_id}"
end
end
在我的convos控制器中,创建方法,我尝试了几件事:
convos_controller.rb
def create
@convo = Convo.create!({sender_id: @sender_id, recipient_id: @recipient_id})
ActionCable.server.subscribe(@convo.id)
end
ActionCable.subscribe(@convo.id)
错误:
NoMethodError (undefined method
订阅'ActionCable:Module)`
ActionCable.msgs.subscribe(@convo.id)
错误:
ActionCable的NoMethodError (undefined method
msgs':模块):`
App.msgs.subscribe(@convo.id)
错误:NameError (uninitialized constant ConvosController::App):
MsgsChannel.subscribe(@convo.id)
错误:NoMethodError (undefined method
订阅了MsgsChannel:Class`
ActionCable.server.subscribe(@convo.id)
错误:NoMethodError (undefined method
订阅'#):`
答案 0 :(得分:3)
从控制器中检索特定频道实例
Channel
个实例与用户的Connection
相关联。以下内容将用于获取Channel
的{{1}}的哈希值:
Connection
(如果conn = ActionCable.server.connections.first { |c| c.current_user == user_id }
# subs is a hash where the keys are json identifiers and the values are Channels
subs = conn.subscriptions.instance_variable_get("@subscriptions")
不存在,请按照the rails ActionCable overview第3.1.1节顶部的说明添加。)
然后,您可以根据自己的标准获得Connection#current_user
。例如,您可以按类型搜索,在您的情况下为Channel
。也可以使用MsgsChannel
中的json密钥,但可能更复杂。
拥有此实例后,您可以调用您想要的任何方法(在您的情况下为subs
)。
对此方法的关注
MsgsChannel#subscribe
只是封装了服务器端工作,这些工作将响应来自应用程序客户端的消息而启动。让服务器调用Channel
方法实际上等于让服务器假装消费者发送了一条它没有发送的消息。
我建议您不要将Channel
和Controller
中使用的任何逻辑放入共享位置的方法中。然后,Channel
和Controller
可以根据需要直接调用此方法。
据说有一个令人痛苦的警告,就是你需要Channel
来呼叫Channel
。不幸的是,管理流特定于stream_from
,尽管从根本上它只是更新Channel
的pubsub信息。
我认为流管理应该只需要适当的连接和Server
及其pubsub。如果是这种情况,您不必担心从应用程序的服务器端调用Server
方法。
如果您获得Channel
,任何stream_for
,您应该能够更直接地有效地运行Channel
(您也可以使用此答案顶部的Channel
)并在其上调用subs
stream_for
我自己没试过,但看起来它应该可行。
答案 1 :(得分:1)
因此,您不应该在创建时将用户订阅到控制器中的频道。它应该基于他们访问页面的时间。您应该通过添加js / coffe文件来更改用户连接的位置,以便根据连接的人员为您执行此操作。我在学习时的一个很好的示例/教程就是这个视频here。
视频遗漏的是如何连接到单个对话。所以我挣扎着找到了一种从网址中获取会话ID的方法,可能不是最好的方式,但它有效。希望这有帮助
Enter