rails 6.0.3
ruby 2.6.3
前提・実現したいこと
作成中のサイトにグループチャット機能を実装したいのですが、数週間行き詰まっています。
https://qiita.com/rhiroe/items/4c4e983e34a44c5ace27
こちらを参考にしています。
発生している問題・エラーメッセージ
自分が作成した部屋で、自分が発言した時は正常にチャットが機能するのですが、他人が作成した部屋で発言すると下記のログが流れ、チャットが機能しない(発言がリアルタイムで反映されない)状況です。
Started GET "/cable" for 122.219.71.8 at 2020-12-11 11:19:11 +0000 Cannot render console from 122.219.71.8! Allowed networks: 127.0.0.0/127.255.255.255, ::1 Started GET "/cable/" [WebSocket] for 122.219.71.8 at 2020-12-11 11:19:11 +0000 Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: upgrade, HTTP_UPGRADE: websocket) User Load (1.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 11], ["LIMIT", 1]] Registered connection (Z2lkOi8vcXVlc3Rib2FyZC9Vc2VyLzEx) RoomChannel is transmitting the subscription confirmation RoomChannel is streaming from room_channel_13 RoomChannel#speak({"message"=>"fdf"}) (1.0ms) begin transaction Recruit Load (2.9ms) SELECT "recruits".* FROM "recruits" WHERE "recruits"."id" = ? LIMIT ? [["id", 13], ["LIMIT", 1]] User Load (2.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 11], ["LIMIT", 1]] Message Create (2.5ms) INSERT INTO "messages" ("content", "recruit_id", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["content", "fdf"], ["recruit_id", 13], ["user_id", 11], ["created_at", "2020-12-11 11:19:14.932226"], ["updated_at", "2020-12-11 11:19:14.932226"]] (5.0ms) commit transaction [ActiveJob] Enqueued MessageBroadcastJob (Job ID: 29bb74ae-38a9-434f-af85-58ce0fd56a5d) to Async(default) with arguments: #<GlobalID:0x00007fc280283b98 @uri=#<URI::GID gid://questboard/Message/389>> Message Load (2.5ms) SELECT "messages".* FROM "messages" WHERE "messages"."id" = ? LIMIT ? [["id", 389], ["LIMIT", 1]] [ActiveJob] [MessageBroadcastJob] [29bb74ae-38a9-434f-af85-58ce0fd56a5d] Performing MessageBroadcastJob (Job ID: 29bb74ae-38a9-434f-af85-58ce0fd56a5d) from Async(default) enqueued at 2020-12-11T11:19:15Z with arguments: #<GlobalID:0x00007fc280999c98 @uri=#<URI::GID gid://questboard/Message/389>> [ActiveJob] [MessageBroadcastJob] [29bb74ae-38a9-434f-af85-58ce0fd56a5d] User Load (2.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 11], ["LIMIT", 1]] [ActiveJob] [MessageBroadcastJob] [29bb74ae-38a9-434f-af85-58ce0fd56a5d] Recruit Load (1.6ms) SELECT "recruits".* FROM "recruits" WHERE "recruits"."id" = ? LIMIT ? [["id", 13], ["LIMIT", 1]] [ActiveJob] [MessageBroadcastJob] [29bb74ae-38a9-434f-af85-58ce0fd56a5d] Rendered messages/_message.html.erb (Duration: 489.6ms | Allocations: 3708810) [ActiveJob] [MessageBroadcastJob] [29bb74ae-38a9-434f-af85-58ce0fd56a5d] Error performing MessageBroadcastJob (Job ID: 29bb74ae-38a9-434f-af85-58ce0fd56a5d) from Async(default) in 525.5ms: ActionView::Template::Error (undefined method `generate_key' for nil:NilClass):
該当のソースコード
参考サイトとは、「room」を「recruit」にしている点とdeviseを使用していない点等が違いますが、他は概ね同じのはずです。
rooms/new.html.erb <%= text_field_tag :content, nil, class: "form-control mb-2", placeholder: "メッセージを入力(200文字以内)", data: { behavior: 'room_speaker'} %> <div class="list-group col-md-12 px-0"> <div id="messages" data-recruit_id="<%= @recruit.id %>"><%= render @messages %></div> </div>
connecrion.rb module ApplicationCable class Connection < ActionCable::Connection::Base #websocketでcurrent_userを使うための処理 identified_by :current_user def connect reject_unauthorized_connection unless find_verified_user end protected def find_verified_user self.current_user = User.find_by(id: cookies.signed[:user_id]) end end end
room_channnel.rb class RoomChannel < ApplicationCable::Channel def subscribed #チャンネル購読時に実行 stream_from "room_channel_#{params['recruit_id']}" end def unsubscribed end def speak(data) # jsで実行されたspeakのmessageを受け取り、room_channelのreceivedにブロードキャストする Message.create!(content: data['message'], user_id: current_user.id, recruit_id: params['recruit_id']) end end
room_channnel.js /*global $*/ import consumer from "./consumer"; // $(function() { ... }); で囲むことでレンダリング後に実行される // レンダリング前に実行されると $('#messages').data('room_id') が取得できない // turbolinks を使っている場合は $(document).on('turbolinks:load', function() { ... }); で囲う $(function() { const chatChannel = consumer.subscriptions.create({ channel: 'RoomChannel', recruit_id: $('#messages').data('recruit_id') }, { connected() { console.log("connected"); }, disconnected() { }, // room_channel.rbでブロードキャストされたものがここに届く received: function(data) { console.log("received"); return $('#messages').prepend(data['message']); }, //サーバー側のspeakメソッドを呼び出す speak: function(message) { console.log("speak : " + message); //message_broadcast_jobのperform(message)に送る return this.perform('speak', { message: message }); } }); $(document).on('keypress', '[data-behavior~=room_speaker]', function(event) { if (event.keyCode === 13) { console.log('enter : ' + event.target.value); chatChannel.speak(event.target.value); event.target.value = ''; return event.preventDefault(); } }); });
message_broadcast_job.rb class MessageBroadcastJob < ApplicationJob queue_as :default def perform(message) ActionCable.server.broadcast "room_channel_#{message.recruit_id}", message: render_message(message) end private def render_message(message) ApplicationController.renderer.render partial: 'messages/message', locals: { message: message } end end
rooms/new.html.erb <%= text_field_tag :content, nil, class: "form-control mb-2", placeholder: "メッセージを入力(200文字以内)", data: { behavior: 'room_speaker'} %> <div class="list-group col-md-12 px-0"> <div id="messages" data-recruit_id="<%= @recruit.id %>" data-user_id="<%= current_user.id %>" ><%= render @messages %></div> </div>
message.rb class Message < ApplicationRecord belongs_to :recruit belongs_to :user validates :content, presence: true, length: { maximum: 200 } # createの後にコミットする { MessageBroadcastJobのperformを遅延実行 引数はself } after_create_commit { MessageBroadcastJob.perform_later self } end
試したこと
・https://qiita.com/take18k_tech/items/00cc14c0eff45073ffc7
こちらを参考にしてやってみましたが別の問題で上手くいきませんでした。
・チャットが機能しない時は下記の実行結果がnilになっている事を確認。
message_broadcast_job.rb (byebug) ApplicationController.renderer.render partial: 'messages/message', locals: { message: message }
・チャットが正常に機能する時としない時で"ApplicationController.renderer"の実行結果が違う事を確認。
チャットが機能しない時は下記の後に長々とログが流れます。(文字数制限のため省略します)
チャットが正常に機能する時 message_broadcast_job.rb (byebug) ApplicationController.renderer #<ActionController::Renderer:0x00007fbc1d67d4d8 @controller=ApplicationController, @defaults={:http_host=>"example.org", :https=>false, :method=>"get", :script_name=>"", :input=>""}, @env={"HTTP_HOST"=>"example.org", "HTTPS"=>"off", "REQUEST_METHOD"=>"GET", "SCRIPT_NAME"=>"", "rack.input"=>"", "rack.url_scheme"=>"http"}>
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。