KTC 27インチモニターWQHD (2560x1440) Fast IPS 180Hz 1ms(MPRT) 124%sRGBゲーミングモニター低ブルーライトフリッカーフリーFreeSync & G-Sync対応高輝度350cd/m² PS5対応HDMI×2 DP×1 3年保証H27T22C
¥29,980 (2025年4月25日 13:08 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)Amazon Fire HD 10 タブレット - 10インチHD ディスプレイ 32GB ブラック
¥19,980 (2025年4月25日 13:07 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)
Rails で Action Cable の config.action_cable.url
を設定しなくても動いたのだけども…
Rails8 から Solid Cable が標準搭載されるようになりましたね。
それによって、Redisを使用しなくてもリアルタイム機能の実装がグッと楽になりました! これによって WebSocket を使ったリアルタイム性のあるユーザー体験を少し楽に提供できます。
ところで、Action Cable の設定を見ていると config/environments/*.rb
ファイルに config.action_cable.url
という項目があります。これは WebSocket サーバーの URL を設定するもののようですが…
「あれ?これ設定しなくても Action Cable 動いてるぞ?」
「仮で入れていたURLなのに Action Cable 動いてるぞ?」
なんて思ったことはありませんか?(あまりないかもしれません)
実は、クライアント側(Vue, React など)で WebSocket の接続先 URL をちゃんと指定していれば、config.action_cable.url
は多くの場合、設定不要です。
この記事では、その理由を Rails の情報も交えながら、少し掘り下げて解説していきます。
そもそも config.action_cable.url
さんのお仕事は?
まず、この設定項目が本来何のために用意されているのかを見てみましょう。Railsガイドによると、モノリシックな実装を行う際にフロントエンドへaction_cableの値を伝えるためのaction_cable_meta_tag
で使われることが説明されています。
action_cable_meta_tag
は、クライアントサイド JavaScript が接続先を知るための タグを HTML に出力するビューヘルパーです。
name="action-cable-url" content="ws://localhost:3000/cable">
では、このヘルパーは config.action_cable.url
をどのように使うのでしょうか?
実際の Rails のソースコード (ActionCable::Helpers::ActionCableHelper
) を確認すると、このヘルパーは以下のように動作します。
- まずアプリケーション設定の
config.action_cable.url
を参照します - もし
config.action_cable.url
が設定されていなければ、config.action_cable.mount_path
(デフォルトは/cable
) に基づいて URL を自動生成します
rails/actioncable/lib/action_cable/helpers/action_cable_helper.rb
def action_cable_meta_tag
tag "meta", name: "action-cable-url", content: (
ActionCable.server.config.url ||
ActionCable.server.config.mount_path ||
raise("No Action Cable URL configured -- please configure this at config.action_cable.url")
)
end
このように、config.action_cable.url
は、主に action_cable_meta_tag
ヘルパーが URL を決定する際に(優先的に)参照する設定、という位置づけになります。
Frontend も Rails で完結させるアプリケーション構成(いわゆるモノリス構成)では、ページに埋め込まれた JavaScript がこのメタタグを読み取って、「あ、WebSocket サーバーはここね!」と接続先を知る、という使い方をしていました。このメタタグの content
に config.action_cable.url
の値が使われるわけです(設定されていなければ、デフォルトの /cable
パスが使われます)。
この時点で既にあれ?API modeの時はじゃあ使わなくていいのでは?となると思いますが、その通りです。
なぜ設定なしでも動くのか? API mode × モダンフロントエンドのような場合
では、なぜ config.action_cable.url
を設定しなくても、Vue や React を使ったアプリケーションで Action Cable が動くのでしょうか? 答えはクライアント側の実装にあります。
- クライアントライブラリ
@rails/actioncable
Vue や React などのフロントエンドフレームワークから Action Cable を使う場合、通常 npm
や yarn
で @rails/actioncable
という JavaScript ライブラリをインストールします。
npm install @rails/actioncable
# or
yarn add @rails/actioncable
# etc...
-
createConsumer()
で接続先を直接指定
このライブラリの中心的な機能の一つが createConsumer()
関数です。これを使って WebSocket サーバーへの接続(Consumer)を作成するのですが、この関数には接続先の WebSocket URL を直接引数として渡せます
Rails ガイドにもしっかり書かれています。
4.1.1. Connect Consumer
// app/javascript/channels/consumer.js // Action Cable provides the framework to deal with WebSockets in Rails. // You can generate new channels where WebSocket features live using the `bin/rails >generate channel` command. import { createConsumer } from "@rails/actioncable" export default createConsumer()
This will ready a consumer that’ll connect against /cable on your server by default. >The connection won’t be established until you’ve also specified at least one >subscription you’re interested in having.
The consumer can optionally take an argument that specifies the URL to connect to. >This can be a string or a function that returns a string that will be called when the >WebSocket is opened.
// Specify a different URL to connect to createConsumer('wss://example.com/cable') // Or when using websockets over HTTP createConsumer('https://ws.example.com/cable') // Use a function to dynamically generate the URL createConsumer(getWebSocketURL) function getWebSocketURL() { const token = localStorage.get('auth-token') return `wss://example.com/cable?token=${token}` }
つまり、Vue や React のコードの中で、
import { createConsumer } from "@rails/actioncable"
// .env ファイルなどから URL を取得するのがベスト
const wsUrl = 'ws://localhost:3000/cable'
const consumer = createConsumer(wsUrl)
// あとは consumer を使って Channel をsubscribe...
のように、接続先の URL を JavaScript 側で明示的に指定してしまえば、Rails 側の config.action_cable.url
設定や action_cable_meta_tag
ヘルパーは全く必要なくなるわけです。クライアント自身が接続先を知っているので、サーバーに教えてもらう必要がないんですね。
サーバー内部のブロードキャストは URL を見ていない
「でも、サーバー側で ActionCable.server.broadcast
するときに URL が必要じゃないの?」という疑問も湧くかもしれません。
答えは「通常は不要」です。
Rails アプリケーション内部(モデルのコールバック、コントローラーのアクション、ジョブなど)からブロードキャストを行う場合、Action Cable は config/cable.yml
で設定された Pub/Sub アダプタ (async
, redis
, postgresql
, solid_cable
など) を介してメッセージを配信します。
今回は私がSolid Cableを使用しているので、solid_cable
です
# config/cable.yml (例)
development:
adapter: solid_cable
production:
adapter: solid_cable
polling_interval: 0.1.seconds
message_retention: 1.day
async
や solid_cable
なら同じプロセスやDB内で、redis
や postgresql
ならRedisサーバーや、LISTEN / NOTIFY
という非同期通知メカニズムを利用して、「このチャンネルを購読している人たちにこのデータを送って!」という指示が伝わります。この仕組みにおいて、外部からアクセス可能な WebSocket の URL (config.action_cable.url
で設定するようなもの) は直接的には使われません。
まぁ、railsの中のことなので絶対パスがなくても大丈夫みたいな感じでしょうか
じゃあ、config.action_cable.url
はいつ使うの? (補足)
この設定が完全に無意味かというと、そうでもありません。以下のような少し特殊なケースでは設定が必要になることがあります。
- Rails のビューで
action_cable_meta_tag
を使って URL をクライアントに伝えたい場合(最もベーシックな使い方) - Rails アプリケーション外部のプロセス(例: 別のマイクロサービス、独立した Rake タスクなど)から Action Cable サーバーにブロードキャストしたい場合に、その接続先としてこの URL が必要になることがあります(ただし、このケースはあまり想像がつかないので無いかもしれません)
- Action Cable のテストで URL を明示的に設定する必要がある場合(テストは大事ですが、何かしらのAPIを叩いたら発火や、DBの登録で発火などの実装が多いと思いますので、そのAPIを叩いてテストすればいいと思います)
まとめ
以下の条件が揃っていれば、config.action_cable.url
を設定しなくても Action Cable は問題なく動作します。
- クライアント側 (Vue, React など) で
@rails/actioncable
を使い、createConsumer()
で WebSocket の URL を直接指定している - サーバーからのブロードキャストは Rails アプリケーション内部から行われている
- Rails のビューヘルパー
action_cable_meta_tag
を使っていない
調べてみると、これはどうやらバグや偶然ではなく、Rails の設計通りの挙動だったようです。
モダンな Rails API + SPA (Single Page Application) 構成では、この設定は省略できることが多いので、config/environments/*.rb
が少しスッキリするかもしれません。
ただし、あったらエラーになるというわけでもないので、将来的に上記の「必要になるケース」が発生する可能性も考慮して、明示的に設定しておく、という判断ももちろんアリだと思います!
参考: