如何在rails控制器中调用通道方法?

时间:2017-03-08 19:01:18

标签: ruby-on-rails ruby ruby-on-rails-3 actioncable

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

2 个答案:

答案 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方法实际上等于让服务器假装消费者发送了一条它没有发送的消息。

我建议您不要将ChannelController中使用的任何逻辑放入共享位置的方法中。然后,ChannelController可以根据需要直接调用此方法。

据说有一个令人痛苦的警告,就是你需要Channel来呼叫Channel。不幸的是,管理流特定于stream_from,尽管从根本上它只是更新Channel的pubsub信息。

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

如果您获得Channel,任何stream_for,您应该能够更直接地有效地运行Channel(您也可以使用此答案顶部的Channel )并在其上调用subs

stream_for

我自己没试过,但看起来它应该可行。

答案 1 :(得分:1)

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

视频遗漏的是如何连接到单个对话。所以我挣扎着找到了一种从网址中获取会话ID的方法,可能不是最好的方式,但它有效。希望这有帮助

Enter