Rails8に入るsolid_queueなどのgemを使った時のdatabase.ymlの書き方

  • このエントリーをはてなブックマークに追加

スポンサーリンク

Rails8からデフォルトになるsolid_queueなどのgemについて、本番環境を想定したときにdatabase.ymlの書き方で少し問題に直面したので備忘録として記事にしたいと思います。

Solid系のgemについて

Rails8からデフォルトで以下のgemが設定されるようになっています。

これらは全てバックエンドのアダプターにRedisではなくデータベースを使用するように作られています。

Railsの記事やリポジトリを見ていると、今後はRedisなどのミドルウェアを使用しなくても本番環境でアプリケーションを動かせるようにしたいのかなーと思います。

それぞれのREADMEにインストール方法が書いていますが、その中でdatabase.ymlは以下のようなコードが示されています。

production:
  primary: &primary_production
    <<: *default
    database: app_production
    username: app
    password: <%= ENV["APP_DATABASE_PASSWORD"] %>
  queue:
    <<: *primary_production
    database: app_production_queue
    migrations_paths: db/queue_migrate

直面した問題

本番環境においては、データベース周りの接続情報については秘匿情報のため環境変数を使用すると思います。

さらにRailsはDATABASE_URLという環境変数が設定されていれば、その内容を優先してデータベース接続を行うように作られています。

Railsガイド参考

こんな感じのやつ

ENV["DATABASE_URL"] # => "postgresql://localhost/blog_development?pool=5"

なので、本番環境ではDATABASE_URLに値を設定してデプロイすることもあるんですが、solid系のgemではそれぞれテーブルが異なるため、例えば

  • DATABASE_URL : 本体用
  • DATABASE_QUEUE_URL : solid_queue用
  • DATABASE_CACHE_URL : solid_cache用
  • DATABASE_CABLE_URL : solid_cable用

のように4つの環境変数を設定したほうがいいのか、もしくはREADMEのサンプルのようにパスワード、エンドポイントなどを環境変数にしてDATABASE_URLを使わないほうがいいのか悩みました。

ただ、個人的に環境変数が多いと運用コストがかかるし、基本的にはテーブル名はapp_production_queueなどのように末尾が異なるケースが多いと思ったので、DATABASE_URLだけで何とかできないかと考えました。

解決方法

最終的にdatabase.ymlを以下のコードにしました。

production:
  primary: &primary_production
    <<: *default
    url: <%= ENV["DATABASE_URL"] %>
  cache:
    <<: *primary_production
    url: <%= ENV["DATABASE_URL"]&.+("_cache") %>
    migrations_paths: db/cache_migrate
  queue:
    <<: *primary_production
    url: <%= ENV["DATABASE_URL"]&.+("_queue") %>
    migrations_paths: db/queue_migrate
  cable:
    <<: *primary_production
    url: <%= ENV["DATABASE_URL"]&.+("_cable") %>
    migrations_paths: db/cable_migrate

urlを使うことで、環境変数にDATABASE_URLが指定されていても上書きされます。

そしてdatabase.yml内で明示的にENV[“DATABASE_URL”]を使うことで、solid系の指定は文字列の結合という形にしました。

これであれば、管理すべき環境変数はこれまで通りDATABASE_URLだけなので簡単です。

ちなみに、&. とnilガードにしているのはdevelopment環境などでもdatabase.ymlは読み込まれるので、エラーにならないようにするためです。

他にも良い方法があるかもしれませんが、環境変数の管理を最小限にするには良い方法ではないでしょうか。

スポンサーリンク

  • このエントリーをはてなブックマークに追加