rails 5 - 通过ActionCable为每个对话创建频道

时间:2016-07-14 23:34:17

标签: ruby-on-rails websocket chat actioncable

我是一名新的Rails开发人员,并开始在Rails 5中使用ActionCable来创建聊天应用程序。

问题是因特网上有很多使用ActionCable的聊天示例,但所有这些都非常简单。他们创建了一个频道,所有连接到该频道的用户都可以发送或阅读其他人的消息。

例如,他们创建一个像这样的聊天频道:

class ChatChannel < ApplicationCable::Channel
  def subscribed
    stream_from 'messages'
  end

  def speak(data)
    ActionCable.server.broadcast('messages',
      message: render_message(data['message']))
  end

  private

  def render_message(message)
    ApplicationController.render(partial: 'messages/message',
                                 locals: { message: message })
  end
end

在客户端,他们连接到该频道

App.chat = App.cable.subscriptions.create "ChatChannel",
  received: (data) ->
    $('#messages').append(data.message)

  speak: (msg) ->
    @perform 'speak', message: msg

如何在2个用户之间为每个对话创建一个频道?

1 个答案:

答案 0 :(得分:6)

唯一改变的是您订阅的频道。在这种情况下,应该是一个特定的对话。你可以这样:

messages.coffee

$(document).on "turbolinks:load", ->
  messages = $("#messages-list")

  App.Messages = App.cable.subscriptions.create {
    channel: "MessagesChannel"
    # You can grab the conversation id as a data attribute from the messages container of your conversation and pass it as a parameter to the channel
    conversation_id: messages.data("conversation-id")
  },

  connected: ->

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

  received: (data) ->
    messages.append(data["message"])
    $("#new_message")[0].reset();

messages_channel.rb

class MessagesChannel < ApplicationCable::Channel
  def subscribed
    stream_from "conversation_#{params['conversation_id']}_channel"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end
end

messages_controller.rb

# You can have something like this in your create action
def create
    message = @conversation.messages.build(message_params)
    message.user = current_user
    message.save

    ActionCable.server.broadcast "conversation_#{message.conversation.id}_channel",
      message: render_message(message)

    head :ok
end

private

  def set_conversation
    @conversation = Conversation.find(params[:conversation_id])
  end

  def render_message(message)
    render partial: "messages/message", locals: { message: message }
  end