前提・実現したいこと
Action CableとAjax通信を用いてリアルタイムでチャットできるシステムを作っています。
ログインしているユーザーか否かでメッセージの表示位置を分けたところ、非同期通信によるメッセージのやり取りができなくなってしまいました。
(表示位置を分けるまでは非同期通信によるリアルタイムのチャットができていました。)
機能概要(テーブルの種類)
- ユーザー管理機能の実装
- ルーム管理機能
- メッセージ投稿機能
- ユーザーとルームの中間テーブル
機能の詳細
メッセージの送受信にはAction CableとAjaxを用いて実装しています。
送信の際はAciton Cableのspeakメソッドは使わずに、Ajaxを用いています。
ログインしたユーザーはルームの選択をすることが出来て、同じルームにいるユーザー全員とリアルタイムでチャットができます。
メッセージはログインしているユーザーか否かで、表示位置を分けています。
また、メッセージも各ルームにネストして、ルームごとに表示しています。
メッセージは無限スクロール機能を実装しており、新しい100件のみのメッセージの読み込みとなっています。
発生している問題・エラーメッセージ
メッセージの投稿をした際に、メッセージがリロードしないと読み込まれないという不具合が発生しています。
このエラーは、ユーザーによってメッセージの表示位置を変更する機能を実装するまではなかったエラーになります。
ターミナルにて確認すると以下のような結果が反映されることから、メッセージ表示の条件分岐またはそれに関するファイルにて問題が起きているものと思うのですが、その問題を見つけられません。
ActionView::Template::Error (Devise could not find the `Warden::Proxy` instance on your request environment. Make sure that your application is loading Devise and Warden as expected and that the `Warden::Manager` middleware is present in your middleware stack. If you are seeing this on one of your tests, ensure that your tests are either executing the Rails middleware stack or that your tests are using the `Devise::Test::ControllerHelpers` module to inject the `request.env['warden']` object for you.): 1: <div class="message" id="message-<%= message.id %>"> 2: <% if message.user_id == current_user.id %> 3: <div class="right_message"> 4: <p class="my_message_name"><%= message.user.nickname %></p> 5: <div class="my_message_content"> app/views/messages/_message.html.erb:2 app/models/message.rb:8:in `template' app/controllers/messages_controller.rb:6:in `create'
※ブラウザのコンソール上に下記の表示もされていましたので、こちらも追記しておきます。
on_content_end.js:54 on_content_end ==>response to loadPagePattern, href=http://localhost:3000/rooms/2, pattern.id=undefined
_message.html.erb
ruby
1<div class="message" id="message-<%= message.id %>"> 2 <% if message.user_id == current_user.id %> 3 <div class="right_message"> 4 <p class="my_message_name"><%= message.user.nickname %></p> 5 <div class="my_message_content"> 6 <%= simple_format(h message.content) %> 7 </div> 8 </div> 9 <% else message.user_id != current_user.id %> 10 <div class="left_message"> 11 <div class="your_message"> 12 <p class="your_message_name"><%= message.user.nickname %></p> 13 <div class="your_message_content"> 14 <%= simple_format(h message.content) %> 15 </div> 16 </div> 17 </div> 18 <% end %> 19</div>
message_controller.rb
ruby
1class MessagesController < ApplicationController 2 def create 3 @room = Room.find(params[:room_id]) 4 @message = current_user.messages.create!(message_params) 5 ActionCable.server.broadcast "room_channel", message: @message.template 6 end 7 8 private 9 def message_params 10 params.require(:message).permit(:content).merge(room_id: @room.id) 11 end 12end 13
message.rb
ruby
1class Message < ApplicationRecord 2 belongs_to :user 3 belongs_to :room 4 validates :user_id, presence: true 5 validates :content, presence: true, length: { maximum: 500 } 6 7 def template 8 ApplicationController.renderer.render partial: "messages/message", locals: { message: self } 9 end 10end 11
rooms_controller
ruby
1class RoomsController < ApplicationController 2 3 def index 4 @rooms = Room.all.order(:id) 5 end 6 7 def new 8 @room = Room.new 9 @room.users << current_user 10 end 11 12 def create 13 @room =Room.new(room_params) 14 if @room.save 15 redirect_to root_path 16 else 17 render :new 18 end 19 end 20 21 def show 22 @room = Room.find(params[:id]) 23 @messages = @room.messages.includes(:user).order(:id).last(100) 24 @message = current_user.messages.build 25 end 26 27 def show_additionally 28 last_id = params[:oldest_message_id].to_i - 1 29 @messages = Message.includes(:user).order(:id).where(id: 1..last_id).last(50) 30 end 31 32 private 33 34 def room_params 35 params.require(:room).permit(:name).merge(user_ids: current_user.id) 36 end 37end
show.html.erb(rooms)
ruby
1<div id="message-container" data-room_id = "<%= @room.id %>"> 2 <%= render @messages %> 3</div> 4<%= render 'footer' %>
補足情報(FW/ツールのバージョンなど)
- Ruby ver 2.6,5
- Ruby on Rails ver 6.0.0
あなたの回答
tips
プレビュー