首页 > 解决方案 > 将 Actioncable 与 Rails 集成时出错

问题描述

我正在尝试建立一个群聊系统,群组成员可以在群组的聊天部分留下评论。我正在使用带有 Rails 5 的 Actioncable 来实时实现这一点,但我无法克服一个特定的障碍。聊天评论照常发布到数据库中,但渲染和实时功能出现错误。以下是所有附属代码示例和来自我的终端的错误。我已经为此工作了很多年。我迫切需要启蒙。

错误:( 整个错误消息很长,但这是错误开始的地方。)

Finished "/cable/" [WebSocket] for 127.0.0.1 at 2018-06-25 18:11:13 -0500
GroupChatCommentsChannel stopped streaming from group:5:group_chat_comments
Started GET "/cable" for 127.0.0.1 at 2018-06-25 18:11:13 -0500
Started GET "/cable/" [WebSocket] for 127.0.0.1 at 2018-06-25 18:11:13 -0500
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
GroupChatCommentsChannel is transmitting the subscription confirmation
GroupChatCommentsChannel#follow({"group_id"=>5})
GroupChatCommentsChannel is streaming from group:5:group_chat_comments
Started POST "/groups/5/group_chat_comments" for 127.0.0.1 at 2018-06-25 18:11:50 -0500
Processing by GroupChatCommentsController#create as JS
  Parameters: {"utf8"=>"✓", "group_chat_comment"=>{"body"=>"2"}, "commit"=>"Comment", "group_id"=>"5"}
  Group Load (0.4ms)  SELECT  `groups`.* FROM `groups` WHERE `groups`.`id` = 5 LIMIT 1
  User Load (0.2ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 1 ORDER BY `users`.`id` ASC LIMIT 1
   (0.2ms)  BEGIN
  Group Load (0.3ms)  SELECT  `groups`.* FROM `groups` WHERE `groups`.`id` = 5 LIMIT 1
  SQL (5.8ms)  INSERT INTO `group_chat_comments` (`body`, `user_id`, `group_id`, `created_at`, `updated_at`) VALUES ('2', 1, 5, '2018-06-25 23:11:50', '2018-06-25 23:11:50')
   (7.2ms)  COMMIT
[ActiveJob] Enqueued RenderGroupChatCommentJob (Job ID: ddceb77d-7c5c-42a3-8570-55d09a569c9e) to Async(default) with arguments: #<GlobalID:0x007f87af0ff7d8 @uri=#<URI::GID gid://news/GroupChatComment/4>>
  Rendering group_chat_comments/create.js.erb
  Rendered group_chat_comments/_new.html.erb (1.8ms)
  Rendered group_chat_comments/create.js.erb (31.6ms)
Completed 200 OK in 201ms (Views: 75.1ms | ActiveRecord: 36.5ms)


  GroupChatComment Load (0.2ms)  SELECT  `group_chat_comments`.* FROM `group_chat_comments` WHERE `group_chat_comments`.`id` = 4 LIMIT 1
[ActiveJob] [RenderGroupChatCommentJob] [ddceb77d-7c5c-42a3-8570-55d09a569c9e] Performing RenderGroupChatCommentJob (Job ID: ddceb77d-7c5c-42a3-8570-55d09a569c9e) from Async(default) with arguments: #<GlobalID:0x007f87ab6a1960 @uri=#<URI::GID gid://news/GroupChatComment/4>>
[ActiveJob] [RenderGroupChatCommentJob] [ddceb77d-7c5c-42a3-8570-55d09a569c9e]   Rendered group_chat_comments/_group_chat_comment.html.erb (26.1ms)
[ActiveJob] [RenderGroupChatCommentJob] [ddceb77d-7c5c-42a3-8570-55d09a569c9e] Error performing RenderGroupChatCommentJob (Job ID: ddceb77d-7c5c-42a3-8570-55d09a569c9e) from Async(default) in 60.85ms: ActionView::Template::Error (No route matches {:action=>"show", :controller=>"group_chat_comments", :group_id=>nil, :id=>"4"}, missing required keys: [:group_id]):

编码:

路线:

  resources :groups do
    resources :group_chat_comments
  end

  mount ActionCable.server => '/cable'

模型:

class GroupChatComment < ApplicationRecord
  belongs_to :user
  belongs_to :group

  after_create_commit { RenderGroupChatCommentJob.perform_later self }
end

控制器:

class GroupChatCommentsController < ApplicationController
  before_action :set_group
  before_action :authenticate_user!

  def create
    @group_chat_comment = GroupChatComment.create! body: params[:group_chat_comment][:body], group_id: @group.id, user: current_user
  end

  def destroy
    @group_chat_comment = GroupChatComment.find(params[:id])

    @group_chat_comment.destroy
      redirect_to @group
  end

  private

  def set_group
    @group = Group.find(params[:group_id])
  end
end

工作:

class RenderGroupChatCommentJob < ApplicationJob
  queue_as :default

  def perform(group_chat_comment)
    ActionCable.server.broadcast "group:#{group_chat_comment.group_id}:group_chat_comments", foo: render_group_chat_comment(group_chat_comment)
  end

  private
    def render_group_chat_comment(group_chat_comment)
      ApplicationController.renderer.render(partial: 'group_chat_comments/group_chat_comment', locals: { group_chat_comment: group_chat_comment })
    end
end

渠道:

class GroupChatCommentsChannel < ApplicationCable::Channel
  def follow(params)
    stop_all_streams
    stream_from "group:#{params['group_id'].to_i}:group_chat_comments"
  end

  def unfollow
    stop_all_streams
  end
end

频道 CoffeeScript:

App.group_chat_comments = App.cable.subscriptions.create "GroupChatCommentsChannel",
  collection: -> $('#group_chat_comments')

  connected: ->
    setTimeout =>
      @followCurrentGroup()
    , 1000

  disconnected: ->

  followCurrentGroup: ->
    groupId = @collection().data('group-id')
    if groupId
      @perform 'follow', group_id: groupId
    else
      @perform 'unfollow'

  received: (data) ->
    @collection().append(data['group_chat_comment'])

电缆.js:

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

(function() {
  this.App || (this.App = {});
  App.cable = ActionCable.createConsumer();
}).call(this);

观点:

创建.js:

$('#new_group_chat_comment').replaceWith('<%=j render 'group_chat_comments/new', group: @group %>');

_group_chat_comment 部分:

<% cache group_chat_comment do %>
  <div class="group_chat_comment">
    <p>
      <%= group_chat_comment.body %>
      <%= link_to 'Delete', group_group_chat_comment_path(@group, group_chat_comment), method: :delete %>
    </p>
  </div>
<% end %>

_group_chat_comments 部分:

<%= render 'group_chat_comments/new', group: @group %>

<section id="group_chat_comments" data-group-id="<%= @group.id %>">
  <%= render @group.group_chat_comments %>
</section>

_新部分:

<%= form_for [ @group, GroupChatComment.new ], remote: true do |f| %>
  <div class="group-comment">
    <%= f.text_area :body %>
  </div>
    <br>
  <div class="group-comment-submit">
    <%= f.submit 'Comment' %>
  </div>
<% end %>

标签: javascriptruby-on-railsruby-on-rails-5actioncablerails-activejob

解决方案


推荐阅读