0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

solid cableを使用したwebsocket通信(turbo未使用)

Last updated at Posted at 2025-08-14

solid cableを使ったwebsocket通信をturboフレームなしで実装してみました。
使用しなかった理由は、自分のプロダクトのバージョンとturbo-railsやimportmapが合わず、不具合が発生したからです。

solid cableのみでのwebsocketの実装はあまり記事などなかったので簡単にまとめておこうかなと思いました。solid cableのinstallは完了しているものとしておきます。
間違いや粗い部分があるかもしれません。🙇

実装フロー

  1. application(server)側でchannelを作成する
  2. client(webブラウザ)側でsubscribeするコードを書く
  3. 任意にbroadcastする
  4. js側で必要な処理(appendなど)を実装する
rails g channel Message

とすると下記が作成されます。

app/channels/message_channel.rb
app/channels/application_cable/channel.rb
app/channels/application_cable/connection.rb
test/channels/message_channel_test.rb

sprocketの場合は下記ファイルも必要となります。私は自動追加されなかったので手動で作成しました。

app/assets/javascripts/channels/consumer.js
app/assets/javascripts/channels/index.js
app/assets/javascripts/channels/message_channel.js

それぞれの中身はこちらです。connection.rbとchannel.rbはそのままにしています。


app/channels/message_channel.rb
# app/channels/message_channel.rb
class MessageChannel < ApplicationCable::Channel
  def subscribed
    # クライアントがこのチャネルを購読したときに実行されます。
    # ここで、特定のストリーム(例: "message_channel")からのメッセージを購読します。
    # stream_from は、ActionCable.server.broadcast で送信されたメッセージを受け取るために必要です。
    stream_from "message_channel"
    logger.debug "[MessageChannel] Subscribed to message_channel"
    logger.debug "[MessageChannel] Current connection ID: #{connection.connection_identifier}"

    # サブスクライブ時にテストメッセージを送信
    test_broadcast
  end

  def unsubscribed
    # チャネルの購読が解除されたときに実行されます。
    # 必要に応じて、ここでクリーンアップ処理を行います。
    logger.debug "[MessageChannel] Unsubscribed from message_channel"
    logger.debug "[MessageChannel] Connection ID: #{connection.connection_identifier}"
  end

  # クライアントからメッセージを受信するためのメソッド
  # クライアント側の JavaScript から `perform("receive", data)` のように呼び出されます。
  def receive(data)
    logger.debug "[MessageChannel] Received message: #{data.inspect}"

    # 受信したデータをそのまま、このチャネルを購読している全てのクライアントにブロードキャストします。
    # これにより、メッセージを送ったクライアント自身も、他の購読者も、そのメッセージを受け取ります。
    ActionCable.server.broadcast "message_channel", data
    logger.debug "[MessageChannel] Broadcasted message: #{data.inspect}"
  end

  private

  def test_broadcast
    logger.debug "[MessageChannel] Attempting test broadcast..."
    begin
      ActionCable.server.broadcast(
        "message_channel",
        { message: "Test broadcast", timestamp: Time.current }
      )
      logger.debug "[MessageChannel] Test broadcast successful"
    rescue => e
      logger.error "[MessageChannel] Test broadcast failed: #{e.message}"
      logger.error e.backtrace.join("\n")
    end
  end
end

app/assets/javascripts/channels/consumer.js
(function() {
  this.App || (this.App = {});
  App.cable = ActionCable.createConsumer();
}).call(this);
app/assets/javascripts/channels/index.js
App = {};
App.cable = ActionCable.createConsumer();
app/assets/javascripts/channels/message_channel.js
App.messageChannel = App.cable.subscriptions.create("MessageChannel", {
  connected: function() {
    console.log("Connected to MessageChannel");
  },

  disconnected: function() {
    console.log("Disconnected from MessageChannel");
  },

  received: function(data) {
    console.log("Received message:", data);
    if (typeof appendMessage === 'function') {
      appendMessage(data, "received");
    }
  },

  speak: function(message) {
    return this.perform('receive', message);
  }
});


また、app/assets/javascripts/application.jsに下記を追加する必要があります。

...
//= require action_cable
//= require channels/consumer
//= require channels/index
//= require channels/message_channel
...

このとき依存関係や他assetのエラーなどが原因なのか、上記を挿入する行を変えるとcableでのsocket通信がうまくいきました

これで配信と取得はうまくいくはずです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?