初学者で実務未経験です。この記事に間違った記載や、
アドバイスがある方はコメントで教えていただけると大変助かります。
はじめに
Rails 8 で作成したアプリを Render にデプロイしたところ、本番環境の起動時に次のようなエラーで失敗しました。
The `cable` database is not configured for the `production` environment.
結論からいうと、Rails 8 では Solid Trifecta という設計が標準となり、キャッシュ・ジョブ・Action Cable などの用途ごとにデータベース接続を分ける構成が前提になっています。
今回のエラーは、Rails アプリが本番環境で cable という名前のデータベース接続設定を探したものの、config/database.yml の production にその設定が定義されていなかったために発生していました。
自分は Rails 7 系までの感覚で production の接続情報だけを用意しており、Rails 8 で必要になる primary / cache / queue / cable という接続構成を反映できていませんでした。
この記事では、エラーメッセージの意味、Rails 8 で標準となった Solid Trifecta の前提知識、そして database.yml の修正内容を整理します。
開発環境
- Rubyのバージョン: 4.0.3
- Railsのバージョン: 8.0.0
- JavaScriptバンドラー: importmap
- CSSフレームワーク: tailwindcss
- 開発環境: Docker
今回のプロジェクトは、ミニアプリ開発を通して実装と技術の検証を行うことを目的としていました。そのため、RailsのHotwireやStimulusで十分だと判断し、JavaScriptのバンドラーツールにはimportmapを採用しました。
Node.jsやYarnを利用したパッケージ管理ツールは導入していません。
エラー文の意味
The `cable` database is not configured for the `production` environment.
このエラーは、次のように分解して読めました。
| 部分 | 意味 |
|---|---|
cable database |
cable という名前のDB接続設定 |
| is not configured | 設定されていない |
for the production environment |
production 環境に対して |
つまり、Rails は本番環境で次のような設定を期待していました。
「productionへのデータベース接続情報に cable というデータベース設定が見つかりません」という意味です。
エラー発生時のdatabase.ymlは、development:、test:、production:の接続情報しか定義していない状態でした。
default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
host: db
username: postgres
password: password
development:
<<: *default
database: myapp_development
test:
<<: *default
database: myapp_test
production:
<<: *default
database: myapp_production
username: myapp
password: <%= ENV["MYAPP_DATABASE_PASSWORD"] %>
この状態で config/cable.yml 側が cable というDB接続を使おうとすると、cable database is not configured というエラーになります。
知っておくと良い前提知識まとめ
従来は外部サービスのRedisを使って処理していたものが、Rails 8 からは用途ごとに接続先を分ける構成に変更されました。
Solid Cache / Solid Queue / Solid Cable。
これらはまとめて Solid Trifecta と呼ばれています。
- cache : キャッシュ用
- queue : ジョブ用
- cable : Action Cable(WebSocket の状態管理用)
Redisとは
PostgresqlのようなRDB(Relational Database)とは違い、キーとバリューのシンプルなデータを保存するタイプのデータベースです。
データの永続化を目的とする場合には向いておらず、一時的なデータ保存先として活用されます。
利用用途としては、キャッシュ、セッションデータ、大量メールなどがあります。
ActionCableとは
通常のRailsアプリケーションと同じスタイル・方法で、リアルタイム機能(WebSocket)をRubyで記述できるようにするためのものです。
bin/rails solid_cable:installコマンドを実行すると、自動的にconfig/cable.ymlが設定されます。
デフォルトでconfig/cable.ymlの設定ファイルを利用します。
バックエンドにDBを使用し、やり取りしたメッセージをDBのテーブルに保存します。
WebSocketとは
その都度の処理で完了するHTTP通信とは異なり、一度接続すると、それ以降はクライアントとサーバーがつながった状態になります。
database.yml をどう直すか
-
development:とtest:は&defaultでエイリアス化した接続情報を使用します -
production:の接続情報は、Renderで自動生成される環境変数<%= ENV["DATABASE_URL"] %>を利用します -
DATABASE_URLを利用するように定義します
default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
host: db
username: postgres
password: password
development:
<<: *default
database: myapp_development
test:
<<: *default
database: myapp_test
production:
primary: &primary_production
<<: *default
url: <%= ENV["DATABASE_URL"] %>
cache:
<<: *primary_production
migrations_paths: db/cache_migrate
cable:
<<: *primary_production
migrations_paths: db/cable_migrate
queue:
<<: *primary_production
migrations_paths: db/queue_migrate
<%= ENV["DATABASE_URL"] %>は、環境によって参照するenvファイルが変わります。
開発環境の時はローカルで作成している.envファイルの変数が参照され、開発時はPassで使用している情報が使用されます。
この違いを理解しておくことが重要です。
今回学んだこと
エラー時の自分の理解
そもそもRender上のWebサービスは、DBもRender上のDBを使っているはず。
なぜ自分のローカル環境にある`database.yml`の`development`、`test`、`production`の部分が
このエラーに関係してくるのか、イメージできない
Action Cableは、Rails 5から実装された、リアルタイム通信(WebSocket)のためのフレームワーク。
これまでは、このリアルタイム通信の処理にはRedis(外部サービス)を使用していたが、Rails 8ではこの通信処理をDBを利用して実行する思想が標準になった。
そのため、Rails 8で作成したプロジェクトにはcable.yml(Action Cableを使用する際の設定を記述するファイル)が自動生成され、デプロイ時にconfig/cable.ymlのproduction環境が読み込まれる仕組みになった。
その設定に基づいてコードが実行されるため、database.yml(データベースへアクセスするための情報をまとめたファイル)に、cableのためのデータベース接続情報を定義する必要がある