🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Action Cable

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

Ruby on Rails 6

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

Q&A

解決済

1回答

1147閲覧

【action cable】received()でレンダリングしたい

pecchan

総合スコア591

Action Cable

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

Ruby on Rails 6

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

0グッド

0クリップ

投稿2021/03/15 12:55

Ruby on Rails6/Action Cableで簡単な1対1のチャットアプリを作りました。

メッセージの送受信は正常に動作してますが、表示部分で困りました。

相手は画面左側、自分は画面右側に表示するため、message.user_id(メッセージ発信者)とcurrent_user.idを比較する必要があります。

以下のように比較して左右に振り分けました。

テンプレートファイル
\app\views\messages_message.html.erb

ruby

1<div class='message' id="message-<%= message.id %>"> 2 <% if current_user_id != message.user.id %> 3 <div class="line__left"> 4 <figure><%= if message.user.avatar.file.nil? then image_pack_tag("no-avatar.jpg", class: "") else image_tag(message.user.avatar.url, class: "") end %></figure> 5 <div class="line__left-text"> 6 <div class="name"><%= message.user.name %></div> 7 <div class="text"><%= %>:<%= message.user.id %>:<%= simple_format(h message.text) %></div> 8 </div> 9 <span class="date"><%= l message.created_at, format: '%Y年%-m月%-d日(%a) %H:%M' %></span> 10 </div> 11 <% else %> 12 <div class="line__right"> 13 <div class="text"><%= %>:<%= message.user.id %>: <%= simple_format(h message.text) %></div> 14 <span class="date"><%= l message.created_at, format: '%Y年%-m月%-d日(%a) %H:%M' %></span> 15 </div> 16 <% end %> 17</div> 18

テンプレートを呼ぶ側
\app\views\rooms\show.html.erb

ruby

1 <div class="message__container" data-room_id="<%= @room.id %>"> 2 <%= render partial: 'messages/message', collection: @messages, locals: { current_user_id: current_user.id} %> 3 </div>

チャットルーム表示時(room/show)は、(DBから取得したデータのため)上記で振り分けられ正常に表示されます。

問題は入力したメッセージです。

上記のテンプレートを使うと、current_userは取得できないため使えません。

そこでreceived(data)のタイミングであれば、current_userと送信者の2点がそろうタイミングなので、ここでレンダリングしようと思いました。

javascript

1import consumer from "./consumer" 2 3document.addEventListener('turbolinks:load', () => { 4 5 // viewからcurrent_userを取得 6 let current_user_id = document.getElementsByClassName('message__current_user_id')[0].getAttribute('value'); 7 8 consumer.subscriptions.create("RoomChannel", { 9 connected() { 10 }, 11 12 disconnected() { 13 }, 14 15 received(data) { 16 17 // viewから取得したcurrent_user_id と 18 // サーバから受信したdata['sent_user'](送信者) 19 // が揃ったので、あとはレンダリングしたい 20 21 } 22 }) 23 24 25 26}); 27 28 29

テンプレート内の処理をhtmlで追加しようと思いました。
↓のように。

javascript

1 received(data) { 2 3 let h = '<div class="message" id="message-' + data['message_id'] + '">' 4 if(current_user_id != data['sent_user']){ 5 h = h + '<div class="line__left">' 6 7 } 8 else{ 9 h = h + '<div class="line__right">' 10 } 11 12 13 // サーバー側から受け取ったHTMLを一番最後に加える 14 messageContainer.insertAdjacentHTML('beforeend', h) 15 */ 16 17 }

ところが、rubyのメソッドも使用しているためすぐにこれはマズイと気付きました。

このような状況です。

何かjsからレンダリングする方法、あるいはもっと良い方法はないでしょうか?
経験少ないため方法が思いつかずにいます。

先輩方どうぞ宜しくお願いします。

補足

ログインに関して
deviseは使ってないです
railsチュートリアルのログイン機能を実装しました

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

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

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

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

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

guest

回答1

0

自己解決

templateで出力し、receivedで一部編集することで対応しました。

投稿2021/03/16 02:21

pecchan

総合スコア591

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問