質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Action Cable

Action Cableは、WebSocketをRailsに組み込む機能。Rails4でオプションとして存在していたWebSocketをRails5で標準機能したものです。Railsアプリケーションと同様のスタイルで、Rubyを用いたリアルタイム機能を記述できます。

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

1433閲覧

【rails6】自分が作成したチャット部屋で発言した時しかチャットが機能しない。

Ayustak

総合スコア30

Action Cable

Action Cableは、WebSocketをRailsに組み込む機能。Rails4でオプションとして存在していたWebSocketをRails5で標準機能したものです。Railsアプリケーションと同様のスタイルで、Rubyを用いたリアルタイム機能を記述できます。

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2020/12/11 12:55

編集2020/12/12 01:18

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"}>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

sessions_helper.rbのcurrent_userを変更する事で正常に動作しました。

sessions_helper.rb def current_user if (user_id = session[:user_id]) @current_user ||= User.find_by(id: user_id) elsif (user_id = cookies.signed[:user_id]) user = User.find_by(id: user_id) if user && user.authenticated?(:remember, cookies[:remember_token]) log_in user @current_user = user end end end

sessions_helper.rb def current_user if (user_id = session[:user_id]) @current_user ||= User.find_by(id: user_id) end end

投稿2020/12/12 02:00

Ayustak

総合スコア30

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問