我正在尝试建立一个群组聊天系统,该群组的成员可以在群组的聊天部分中留下评论。我正在将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
Channel 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);
视图:
Create.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>
_new部分:
<%= 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 %>