如何在heroku上部署动作电缆?

时间:2017-11-10 10:51:03

标签: ruby-on-rails redis actioncable

您好我已经使用rails 5实现了动作电缆。它在本地工作正常,但它不能在heroku上工作。在heroku上,每当我发送任何消息时,它都会发送四条消息,两条重复消息和两条空白消息。这是我的代码: - conversation.js

 App.conversation = App.cable.subscriptions.create("ConversationChannel", {
      connected: function() {},
      disconnected: function() {},
      received: function(data) {
        var conversation = $('#conversations-list').find("[data-conversation-id='" + data['conversation_id'].$oid + "']");
        if (data['window'] !== undefined) {
          var conversation_visible = conversation.is(':visible');

          if (conversation_visible) {
            var messages_visible = (conversation).find('.panel-body').is(':visible');

            if (!messages_visible) {
              conversation.removeClass('panel-default').addClass('panel-success');
              conversation.find('.panel-body').toggle();
            }
            conversation.find('.messages-list').find('ul').append(data['message']);
          }
          else {
            $('#conversations-list').append(data['window']);
            conversation = $('#conversations-list').find("[data-conversation-id='" + data['conversation_id'].$oid + "']"); 
            conversation.find('.panel-body').toggle();
          }
        }
        else {
          conversation.find('ul').append(data['message']);
        }

        var messages_list = conversation.find('.messages-list');
        var height = messages_list[0].scrollHeight;
        messages_list.scrollTop(height);
      },
      speak: function(message) {
        return this.perform('speak', {
          message: message
        });
      },
    });

$(document).on('submit', '.new_message', function(e) {
  e.preventDefault();
  var values = $(this).serializeArray();
  App.conversation.speak(values);
  $(this).trigger('reset');
});

的application.js

// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's
// vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file. JavaScript code in this file should be added after the last require_* statement.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require rails-ujs
// require turbolinks
//= require jquery-3.2.1.min
// require_tree .

(function() {
  $(document).on('click', '.toggle-window', function(e) {
    e.preventDefault();
    var panel = $(this).parent().parent();
    var messages_list = panel.find('.messages-list');

    panel.find('.panel-body').toggle();
    panel.attr('class', 'panel panel-default');

    if (panel.find('.panel-body').is(':visible')) {
      var height = messages_list[0].scrollHeight;
      messages_list.scrollTop(height);
    }
  });
})();

Cable.js

//= require action_cable
    //= require_self
    //= require_tree ./channels

        (function() {
          this.App || (this.App = {});

          App.cable = ActionCable.createConsumer();

        }).call(this);

create.js

var conversations = $('#conversations-list');
var conversation = conversations.find("[data-conversation-id='" + "<%= @conversation.id %>" + "']");

        if (conversation.length !== 1) {
          conversations.append("<%= j(render 'conversations/conversation', conversation: @conversation, user: current_user) %>");
          conversation = conversations.find("[data-conversation-id='" + "<%= @conversation.id %>" + "']");
        }

        conversation.find('.panel-body').show();

        var messages_list = conversation.find('.messages-list');
        var height = messages_list[0].scrollHeight;
        messages_list.scrollTop(height);

聊天截图 enter image description here

请让我知道如何解决它。我正在使用带有ruby-2.4.0的rails 5。我也在使用redis服务器进行工作。

1 个答案:

答案 0 :(得分:0)

您设置了一个与ActionCable无关的Javascript event侦听器。

每当您触发submit底部时,您都会调用在页面上附加消息的App.conversation.speak()函数

$(document).on('submit', '.new_message', function(e) {
  e.preventDefault();
  var values = $(this).serializeArray();
  App.conversation.speak(values);
  $(this).trigger('reset');
});

这是您的speak功能

speak: function(message) {
   return this.perform('speak', {
     message: message
   });

我引用Defining The Channel's Subscriber

  

我们使用App.cable.subscriptions.create向我们的消费者添加新订阅。我们为此函数提供了我们要订阅的频道名称的参数ConversationChannel

     

当调用此subscriptions.create函数时,它将调用ConversationChannel#subscribed方法,实际上是回调方法

So what is a callback method?我无法清楚地回答这个问题。

  

此方法负责订阅和流式传输到此频道的消息。

应用程序/信道/ conversation_channel.rb

class ConversationChannel < ApplicationCable::Channel  
  def subscribed
    stream_from 'conversation'
  end
end  

  来自我们的消息广播的

ConversationChannel#subscribed个流,将任何新消息作为JSON发送到客户端订阅功能。

这是我在将Message保存到数据库后实现ActionCable的方法我在MessagesController中触发了Sophie Debenedetto指南中的以下操作(我不知道)如果您将Conversation保存到数据库或Message

  

应用程序/控制器/ messages_controller.rb

class MessagesController < ApplicationController

  def create
    message = Message.new(message_params)
    message.user = current_user
    if message.save
      ActionCable.server.broadcast 'messages',
        message: message.content,
        user: message.user.username
      head :ok
    end
  end

  ...
end

ActionCable.server.broadcast 'messages',received内的App.cable.subscription函数发送调用,该函数负责使用新消息更新页面。

此调用仅针对此事件subscribed的用户执行。订阅通过subscribed

ConversationChannel方法进行管理
App.conversation = App.cable.subscriptions.create('ConversationChannel', {      
  received: function(data) {
      $('#messages').append(this.speak(data));
      },
  speak: function(data) {
      return "<br><p> <strong>" + data.user + ": </strong>" + data.message + "</p>";
      };
  }
});

它以json格式message: message.content, user: message.user.username

从rails控制器传递了以下数据

这些代码中的一部分来自我的应用https://sprachspiel.xyz,这是您可以测试的动作有线应用,该应用仍应正常运行。这是github repository

我相信你正在调用你的js函数两次,或者做一些解决方法来使actioncable工作导致div被追加两次。我相信你正在执行两个不同的时间j来运行动作电缆。

请记住,动作电缆是一个websocket,用于在2个不同的用户/浏览器上更新该消息