2017-03-08 60 views
9

我有一个订阅用户的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:模块)`


ActionCable.msgs.subscribe(@convo.id)

错误: NoMethodError (undefined method封邮件的ActionCable:模块):`


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

尝试基于id的每个对话websocket? –

+0

@TallPaul这是正确的 – gwalshington

回答

1

所以你应该不会将用户订阅到该频道滚上创建。它应该基于他们何时访问该页面。您应该通过添加js/coffe文件来更改用户连接的位置,以便根据连接的人员为您执行此操作。当我学习时,一个很好的例子/教程是这个视频here

视频遗漏的是如何连接到单个对话。所以我努力争取,并找到一种方法来从网址中获取对话ID,可能不是最好的方式,但它的工作原理。希望这有助于

conversation_id = parseInt(document.URL.match(new RegExp("conversations/"+ "(.*)"))[1]) # gets the conversation id from the url of the page 

App.conversation = App.cable.subscriptions.create { channel: "ConversationChannel", conversation_id: conversation_id }, 
    connected: -> 
    # Called when the subscription is ready for use on the server 

    disconnected: -> 
    # Called when the subscription has been terminated by the server 

    received: (data) -> 
    $('#messages').append data['message'] 

    speak: (message) -> 
    @perform 'speak', message: message 
+0

嗨,感谢您的帮助。我已经建立了convo_ids的连接,一切都很好。问题是,在用户会话中,用户使用不同的用户打开一个新的convo,并发送一条消息。这个新的convo尚未订阅,所以用户看不到正确的操作(例如,添加到聊天室的msg)。如何在create方法中从convos控制器调用频道中的订阅方法?谢谢! – gwalshington

3

从控制器

Channel实例与相关检索特定渠道实例用户的Connection。下面的工作得到Channel s的散列的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") 

(如果Connection#current_user不存在,则遵循the rails ActionCable overview在3.1.1节的顶部的说明,将其添加)

然后,您可以根据所需的任何标准获得Channel。例如,您可以按照您的案例搜索MsgsChannelsubs中的json键也可以使用,但可能更复杂。

一旦你有这个实例,然后你可以调用任何你想要的方法(在你的情况下MsgsChannel#subscribe)。

关注有关此方法

一个Channel只是封装,将响应从应用程序的客户端将拉开帷幕邮件服务器端的工作。让服务器调用Channel方法实际上相当于让服务器假装消费者发送了它未发送的消息。

我建议不要这样做,把你想要从ControllerChannel中使用的逻辑放到共享位置的方法中。 ControllerChannel可以根据需要直接调用此方法。

这就是说有一个痛苦的告诫,这是你需要Channel拨打stream_from。不幸的是,管理流特定于Channels,即使它基本上只是更新Server的pubsub信息。

我认为流管理实际上只需要适当的连接,而Server及其pubsub。如果是这种情况,您不必担心从应用程序的服务器端调用Channel方法。

你应该能够有效地运行stream_for更直接,如果你得到一个Channel,任何Channel(你可以使用subs从这个答案的顶部以及),并在其上

conn = ActionCable.server.connections.first { |c| c.current_user == user_id } 
MsgsChannel.new(conn, "made up id").stream_from "your_stream_name" 

我还没打电话stream_for我自己尝试过,但它看起来应该起作用。

+0

这非常有帮助!谢谢Chiune!我在本地测试了您的第一个建议,并且它的工作完美无瑕,但是当我在生产中使用我的虚拟Heroku应用程序进行测试时,它无法正常工作。任何想法为什么? – Amloelxer

+0

@Amloelxer - 不工作你的意思是'subs'不包含你正在寻找的'Channel'实例吗? –

相关问题