Ошибка при интеграции Actioncable с Rails - PullRequest
0 голосов
/ 26 июня 2018

Я пытаюсь создать систему группового чата, где участники группы могут оставлять комментарии в разделе чата группы.Я использую Actioncable с Rails 5 для реализации этого в реальном времени, но не могу преодолеть определенное препятствие.Комментарии чата публикуются в базе данных как обычно, но где-то есть ошибка с функциями рендеринга и реального времени.Ниже приведены примеры кода и ошибка моего терминала.Я работал над этим целую вечность.Я остро нуждаюсь в просветлении.

Ошибка: (полное сообщение об ошибке очень длинное, но именно здесь начинается ошибка.)

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'])

Cable.js:

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

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

Просмотры:

Создать.

_новое частичное:

<%= 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 %>
...