操作电缆:如何仅在Rails 5中的特定聊天室中广播聊天消息?

时间:2017-06-18 03:57:35

标签: angularjs websocket chat ruby-on-rails-5 actioncable

我目前有一个Rails 5应用程序作为我的后端,我们可以称之为" Core。"我还有另一个Angular 1.6.4应用程序作为我的前端,它为Angular客户端提供服务,并通过角度可操作的方式与后端应用程序集成,我们可以称之为" Front"。这是两个完全不同的应用程序,具有完全不同的域。

基本上,我正在尝试通过Core整合Action Cable并让它与Front进行对话。我在这里使用此服务作为Front:enter link description here。至于Core,这只是基本的Action Cable设置。

我在管理员方面有一个聊天室列表。

问题:我从客户端发送了消息,但它向管理端的所有聊天室广播消息。我尝试在流中提供聊天室的特定路径,但仍然向所有聊天室广播消息。

我想将消息广播到特定的聊天室

核心

chat_channel.rb

class ChatChannel < ApplicationCable::Channel
   def subscribed
      stream_from stream_name
   end
   def unsubscribed
     stop_all_streams
   end

   def receive(data)
       ActionCable.server.broadcast stream_name,  data.fetch('message')
   end

   private

   def stream_name
      "chat_channel_#{chat_id}"
   end

   def chat_id
      params.fetch('data').fetch('chat')
   end
end

Fornt

chatCtrl.js

app.run(function (ActionCableConfig){
   ActionCableConfig.debug = true;
   ActionCableConfig.wsUri= "ws://localhost:3000/cable";
});
app.controller('chatCtrl', ['$scope', 'ActionCableChannel',
function($scope, ActionCableChannel) {

  var consumer = new ActionCableChannel("ChatChannel", { chat: 'localhost:3000/#!/chat/1'});
  var callback = function(message) {
    $scope.myData.push(message);
  };
  consumer.subscribe(callback).then(function(){
    $scope.sendToMyChannel = function(message){
      consumer.send(message);
    };
    $scope.$on("$destroy", function(){
      consumer.unsubscribe().then(function(){ $scope.sendToMyChannel = undefined; });
    });
  });
}
]);

1 个答案:

答案 0 :(得分:0)

这是我的问题的解决方案,非常类似于你的问题,但是我没有使用cofeescript,只是javascript ..所以如果你需要我也附上我的代码..我只是检查属性data-chat-room-id来自DOM等于我传递的信息:

消息控制器创建消息然后使用ActionCable.server.broadcast调用这些参数(message,user,chatroom_id,lastuser)我的消息在messages.js中

class MessagesController < ApplicationController
  def create
    message = Message.new(message_params)
    message.user = current_user
    chatroom = message.chatroom
    if message.save
        ActionCable.server.broadcast 'messages',
        message: message.content,
        user: message.user.name,
        chatroom_id: message.chatroom_id,
        lastuser: chatroom.messages.last(2)[0].user.name
      head :ok
    end
  end
end

app/assets/javascrips/channels/messages.js内我检查data.chatroom_id(来自DOM的元素)等于chat_room_id(从控制器发送的元素,刚刚保存的对象消息)

App.messages = App.cable.subscriptions.create('MessagesChannel', {      
  received: function(data) {
    messages = $('#chatroom_id');
    chat_room_id = messages.data('chat-room-id');
    if (data.chatroom_id == chat_room_id) {
      $('#messages').append(this.renderMessage(data));
      };
  },
  renderMessage: function(data) {
      return "<br><p> <strong>" + data.user + ": </strong>" + data.message + "</p>";
  }
});

这篇文章给了我这个答案

Action Cable chat Ilya Bodrov-Krukowski

Ilya Bodrov-Krukowski Github

  

要解决的另一个问题是为我们的脚本提供房间的ID。让我们在HTML data- attribute:

的帮助下解决它      

视图/ chat_rooms / show.html.erb

<div id="messages" data-chat-room-id="<%= @chat_room.id %>">
  <%= render @chat_room.messages %>
</div>
  

有了这个,我们可以在剧本中使用房间的ID:

     

Javascript角/信道/ rooms.coffee

jQuery(document).on 'turbolinks:load', ->
  messages = $('#messages')
  if $('#messages').length > 0

    App.global_chat = App.cable.subscriptions.create {
        channel: "ChatRoomsChannel"
        chat_room_id: messages.data('chat-room-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) ->
        # Data received

      send_message: (message, chat_room_id) ->
        @perform 'send_message', message: message, chat_room_id: chat_room_id