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

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

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

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

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails 6

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Q&A

解決済

1回答

962閲覧

[Rails]非同期通信でチャットできるようにしたい

Tsuyoponta

総合スコア5

Action Cable

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

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails 6

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

0グッド

0クリップ

投稿2021/04/07 00:55

編集2021/04/07 01:01

前提・実現したいこと

Railsでリアルタイムチャットできるアプリを作っています。
Action Cableを用い、非同期通信でチャットできる機能を実装したいのですが、思うようにいきません。
原因が分からなかったので、ご教示いただけたら幸いです。

発生している問題・エラーメッセージ

初めのメッセージは送信ボタンを押すと反映されますが、次のメッセージが送信できない上に、CSSが適用されません。
ブラウザ更新前

ブラウザ更新後は、CSSも適用されて次のメッセージも送信できますが
リアルタイムチャットが実現できていません。

ブラウザ更新後

該当のソースコード

routes.rb

ruby

1Rails.application.routes.draw do 2 devise_for :users 3 root to: "rooms#index" 4 resources :users, only: [:edit, :update] 5 resources :rooms, only: [:new, :create] do 6 resources :messages, only: [:index, :create] 7 end 8end

messages_controller.rb

ruby

1class MessagesController < ApplicationController 2 def index 3 @message = Message.new 4 @room = Room.find(params[:room_id]) 5 @messages = @room.messages.includes(:user) 6 end 7 8 def create 9 @room = Room.find(params[:room_id]) 10 @message = @room.messages.new(message_params) 11 @user = User.find_by(id: current_user.id) 12 if @message.save 13 ActionCable.server.broadcast "message_channel", content: @message, user: @user 14 end 15 end 16 17 private 18 19 def message_params 20 params.require(:message).permit(:content).merge(user_id: current_user.id) 21 end 22end 23

index.html.erb

ruby

1<%= render "shared/header" %> 2 3<div class="wrapper"> 4 <div class="side-bar"> 5 <%= render "side_bar" %> 6 </div> 7 <div class="chat"> 8 <%= render "main_chat" %> 9 </div> 10</div> 11 12<%= render "shared/footer" %>

_main_chat.html.erb

ruby

1<div class="chat-header"> 2 <div class="room-title"> 3 <%= @room.name %> 4 </div> 5 <% if user_signed_in? %> 6 <div class="room-exit"> 7 ルーム退出 8 </div> 9 <% end %> 10</div> 11 12<div class="messages" id="messages"> 13 <%= render partial: "message", collection: @messages %> 14</div> 15 16<% if user_signed_in? %> 17 <%= form_with model: [@room, @message], class: "form", local: true do |f| %> 18 <div class="form-input"> 19 <%= f.text_field :content, class: "form-message", placeholder: "メッセージを入力" %> 20 </div> 21 <%= f.submit "送信", class: "form-submit" %> 22 <% end %> 23<% end %>

_message.html.erb

ruby

1<div class="message"> 2 <div class="upper-message"> 3 <div class="message-user"> 4 <p><%= message.user.nickname %></p> 5 </div> 6 <div class="message-date"> 7 <p><%= message.created_at %></p> 8 </div> 9 </div> 10 <div class="lower-message"> 11 <div class="message-content"> 12 <p><%= message.content %></p> 13 </div> 14 </div> 15</div>

message_channel.js

javascript

1import consumer from "./consumer" 2 3consumer.subscriptions.create("MessageChannel", { 4 connected() { 5 // Called when the subscription is ready for use on the server 6 }, 7 8 disconnected() { 9 // Called when the subscription has been terminated by the server 10 }, 11 12 received(data) { 13 const nickName = `<P>${data.user.nickname}</P>`; 14 const createdAt = `<P>${data.content.created_at}</P>`; 15 const text = `<P>${data.content.content}</P>`; 16 const messages = document.getElementById("messages"); 17 const newMessage = document.getElementById("message_content"); 18 messages.insertAdjacentHTML("beforeend", nickName); 19 messages.insertAdjacentHTML("beforeend", createdAt); 20 messages.insertAdjacentHTML("beforeend", text); 21 newMessage.value=""; 22 } 23}); 24

補足情報(FW/ツールのバージョンなど)

Ruby 2.6.5
Rails 6.0.0
Docker
CircleCI

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

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

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

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

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

guest

回答1

0

自己解決

<%= form_with model: [@room, @message], class: "form", local: true do |f| %>local: truelocal: falseにしたら解決できました。
localオプションは、リモート送信を無効にするかどうかを指定でき、trueにすると無効になるんですね。
デフォルトでAjax通信をするようになっているみたいなので、local: false自体消しても良いと思います。
CSSがブラウザ更新しないと適用されないのは、依然として変わりませんが...

投稿2021/04/07 23:26

Tsuyoponta

総合スコア5

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問