どうもこんにちは,
今回は、リアルタイムのメッセージのやり取りを可能にする
Action Cable
について初心者の僕が初心者の目線に立ち、
かなり丁寧めに
紹介してきたいと思います!
まずは、お使いのエディターを開き、
rails g channel message
このコマンドを打つと、 javascriptのファイルとRubyのファイル どっちもを作ってくれるのでオススメです⭐ (この星記号みずらっ、、)
そして、まずはコントローラーからいじっていきます。
class MessagesController < ApplicationController
def index
@item = Item.find(params[:item_id])アイテムからidを取り出す。
@message = Message.new 新しいの生み出す
@messages = Message.all 全部表示
end
def new
@item = Item.find(params[:item_id])
@message = @item.messages.new 関連付け
@messages = @item.messages
end
def creat
@item = Item.find(params[:item_id])
@message = @item.messages.new(message_params)
ActionCable.server.broadcast 'message_channel', content: @message if @message.save *@messageをcontextに代入
redirect_to "/items/#{@item.id}/messages"メッセージ表示画面にリダイレクト
end
private
def message_params
params.require(:message).permit(:message_text).merge(user_id: current_user.id)
end
end
*マークが付いた contextキーはは後でjavascriptの記述を加える時に使うので忘れずに記入してください。
この後form_withを使うのですが、
form_withを使うと、情報がnewメソッドを通ってcreateメソッドを通ります。
今回はmessage画面の
index画面でやり取りをしたかったので
こうしました
message画面はこんな漢字
<div id='messages'>
<% @item.messages.order(created_at: :DESC).each do |message| %> DESCを使うことで、新しい順で並べてます
<div class = "message-head">
<div class = "message-text">
<p><%= message.message_text %></p>
</div>
<div class="message-box">
<%= message.user.nickname%> //メッセージに紐付いたユーザー名表示
</div>
<% end %>
</div>
<%# 送信ゾーン %>
<div class="box">
<%= form_with(model: [@item, @message], local: true) do |f| %>
<%= f.text_field :message_text, id: "message_text" %>
<%= f.submit '送信' %>
<% end %>
<br/>
<%= link_to '戻る', "/", class: "finish-btn" %></li>
</div>
</div>
form_withのあとのmodel: [@item, @message]は
ネスト構造の時に使います。
つぎはjavascriptに記入していきます
import consumer from "./consumer"
consumer.subscriptions.create("MessageChannel", {
connected() {
// Called when the subscription is ready for use on the server
},
disconnected() {
// Called when the subscription has been terminated by the server
},
received(data) { ここから追加
const html = `<p>${data.content.message_text}</p>`;
const messages = document.getElementById('messages');
const newMessage = document.getElementById('message_text');
console.log(html)
messages.insertAdjacentHTML('afterbegin', html);
newMessage.value='';
ここまで!
// Called when there's incoming data on the websocket for this channel
}
});
ここで先程@messageの値を導入したcontextを使います
afterbeginは第ニ引数のhtmlより後に要素を入れるよ〜
という合図を表しています。
console.logはなくてもいいです。
(確認の為おいて、そのまま忘れてました。。)
packsのapplication.jsに記述がいらないのでお手軽ですよね
はいっ、できました!!
と思ったところで、、
ちょっと待ってください!
ごめんなさい。最後の仕上げがありました。。
最後はサーバー側とクライアント側をつなぐため、
Action Cable特有のメソッドを使っていきます!!
class MessageChannel < ApplicationCable::Channel
def subscribed
# stream_from "some_channel"
stream_from 'message_channel' 加えたところ
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
end
stream_formと
stream_forがあるらしいのですが
stream_formのほうが強力なんだなとだけ理解してます。
詳しく知りたい方はこちら
ActionCableの stream_from
と stream_for
の違いは何ですか?
メッセージ機能の実装は他にもあるらしので、
ActionCableなんてもんつかいたくねーし!
という方は,こちらを参考にお願いします!!
Rails: StimulusReflexとCableReadyでチャット機能を作ってみる
では今回はこれでおしまいにします!
ありがとうございました!