RailsのActionCableを使ってリアルタイムチャット機能を試してみた。


RailsのActionCableの機能を使って、リアルタイムチャットを作ってみた。

しかし、ActionCableの全容をつかむことが出来ず、わかる範囲での記述となります。
間違ったことを書いてある場合は、コメント欄で指摘していただきますと大変助かります。

・目的
HTTP通信では、クライアントがホストに対してリクエストを申請して、初めてデータを取得することができる。
しかし、それでは複数のクライアントがホストにアクセスするような場合に、随時ホストにリクエストしなければデータが取得できない。そのため、ホストとクライアントが相互に監視し、データの変化に即座に反応するウェブページを作る。

・実践
まず、事前準備としてRailsプロジェクトを生成します。
続いて、以下のコマンドでchannelを生成します。channel名はsend_msgです。

rails g channel send_msg

次に、ActionCable.serverをmountするための記述です。

routes.rb
mount ActionCable.server => "/cable"

chat_channel.rbでは、クライアント側のデータをホストに引き渡すための記述となります。
*ざっくり過ぎる表現
subscribedメソッド内でホストにストリームするための値として"room"を定め、send_msgメソッドのActionCable.server.broadcastの後ろにも共通の値が記述されています。

これは、クライアントとホスト間の通信について、あらかじめコネクションのためのインスタンスが生成されており、これをsubscribed(購読と訳されていたが、予約的な意味合い?)して、サーバーにbroadcast(引き渡す的な)する。その具体的な内容はmessage:data['message']ですよ!と素直に読み取りました。
*勝手な解釈なので、お気をつけ下さい。

chat_channel.rb
class ChatChannel < ApplicationCable::Channel
  def subscribed
    stream_from "room"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end

  def send_msg(data)
    ActionCable.server.broadcast "room", message:data['message']
  end
end

続いてchat.coffeeファイルについてです。
先ほどのchat_channel.rbのsend_msgメソッド内の処理で、サーバに引き渡すmessage:data['message']についてsend_msg:(data)の中に記述してあります。

chat.coffee
App.chat = App.cable.subscriptions.create "ChatChannel",
  connected: ->
    console.log("WEBSOCKET CLIANT CONNECTED")

  disconnected: ->
    # Called when the subscription has been terminated by the server

  received: (data) ->
    console.log(data['message'])

  send_msg:(data) ->
    @perform 'send_msg', message:data

chat.coffeeにてApp.cableクラスのサブスクリプションが作られ、それがApp.chatに格納されています。
このApp.chatというインスタンスを用いてindex.html.erbからデータの送受信ができるようになります。

index.html
<h1>チャットルーム</h1><br>
<p id="chat"></p><br>
<p>メッセージ:</p>
<br>
<textarea id="msg" style="width:300px; height:80px;"></textarea>
<hr>
<button id="send">送信</button>
<script>
    $(document).ready(function(){
        /* メッセージ受信 */
        App.chat.received = function(data){
            $("#chat").append(data['message'] + "<br>")
        }

        $("#send").click(function(){
            msg = $("#msg").val()
            /* メッセージ送信 */
            App.chat.send_msg(msg)
        })
    })
</script>

ブラウザを二つ立ち上げて動作を確認できました。

・まとめ
Railsの機能や基礎技術に対する不理解が露呈する場面が多く、よくわからないけど動いているという状況だと思います。ホストとクライアント間の通信をリアルタイムにする機能について、あらためて向き合う必要があるようです。以上です。

参考
Action Cable の概要 : https://railsguides.jp/action_cable_overview.html
Rails WebSocket Chat Real Time : https://www.youtube.com/watch?v=kJbuZecN1c8