Railsには RAILS_ENVと呼ばれる環境を切り替えるための環境変数が用意されています. 最初はこれだけでも十分ですが開発が進むと環境毎に切り替えるプロジェクトがよくあるので備忘録として自分がよくやる対応をまとめてみました.
config_for
config/database.ymlの様に環境毎で切り替える設定はconfig_forというメソッドがあるのでこれを使うとスッキリ書けます.
Rails6 であれば、 shared でマージされるのでデフォルト値が手軽に設定できます.
Rails5を使ってるのであれば、YAMLのAnchors and Aliasesを使ってマージすると便利です.
---
shared:
key3: 'shared value'
base: &base
env: <%= Rails.env %>
key1: "<%= ENV['MY_APP_KEY1'] || 'default' %>"
key2: 'hello %{user_cd}'
production:
<<: *base
module MyApp
class Application < Rails::Application
config.foo = config_for(:foo).deep_symbolize_keys
end
end
Rails.configuration.foo[:key1]
Rails.configuration.foo[:key2].gsub('%{user_cd}', 'dummy1')
Rails.configuration.foo[:key3]
設定より規約を活用して設定を減らす
普通にconfig_forを使ってるとYAMLの設定ファイルの運用が進むにつれて数が増えてきます.
もしくは、既存のシステムがあるとすれば既に膨大な設定になってるかと思います.
そこで設定より規約を使って最初から規約寄りにしておいた方が良いでしょう.
YAMLでは値にkey1: nullとあるとNULL値(Rubyだとnil)になります. key1: 'null' の様にクォートで囲むと文字列の"null"になります.
これを利用して以下の様にしていきます.
---
production:
key1: <%= "'
module MyApp
class Application < Rails::Application
config.foo = config_for(:foo).deep_symbolize_keys
end
end
def config_foo_key1
"${Rails.configuration.foo[:key1] || 'default'}"
end
config_foo_key1 の様に実装側にデフォルト値を用意することで、YAMLの設定ファイル自体がコンパクトになります. baseやshared にデフォルト値を寄せても良いと思います.
このケースの良いところは全ての環境が規約だけで運用できる様になった時、YAMLファイルが不要になるところにあります. 既存のハードコードされた設定があるのであれば、これらの方法を使って減らしていくと良いと思います.
bundle exec rails runner -e development 'puts config_foo_key1
MY_APP_KEY1=foo bundle exec rails runner -e production 'puts config_foo_key1
環境変数にも規約をつける
アプリで固有で使う環境変数にも MY_APP_KEY1 の様に接頭辞MY_APP_の様に規約をつけると良いでしょう.
grepした時に探すのも楽になるし、直感的にアプリ固有の環境変数だということがわかります.
環境毎にユニークな名前空間を使う
ここでの名前空間は以下の様なものを指しています.
AWS S3のバケット名
- ディレクトリのパス
- データベース名
- 全文検索のインデックス名
- キャッシュのキー名
通常、プロダクション環境だと、複数環境が相乗りになることは無いはずですが、デモ環境や開発環境は複数環境が相乗りになることがあります.
含める変数
Railsでは 環境変数 RAILS_ENV があるし、parallel_tests では ENV['TEST_ENV_NUMBER'] を使って並列に動作できるようにしています. さらにアプリ固有の環境変数もある場合もあります.
これらを含めた名前空間にすることで開発環境の様に developmentとtestが同じPCで動かせる様になります.
例えばS3のオブジェクトのキーを考えてみましょう. 環境変数とデモ環境などの実際に動作する物理的な環境であれば MY_APP_ENV の値には demo,prd,stg, qa そして dev の様な値が入るとします.
名前空間は "#{Rails.env}#{ENV['TEST_ENV_NUMBER']}/${ENV['MY_APP_ENV']}" の様な規約にしておきます.
これらの変数の組み合わせが展開されると以下の様になります. 名前空間が重なってないため柔軟に同じサーバや開発環境内に同居できる様になります.
| RAILS_ENV |
TEST_ENV_NUMBER |
MY_APP_ENV |
name space |
| development |
|
dev |
development/dev |
| production |
|
demo |
production/demo |
| production |
|
prd |
production/prd |
| production |
|
stg |
production/stg |
| production |
|
qa |
production/qa |
| test |
|
dev |
test/dev |
| test |
2 |
dev |
test2/dev |
Railsには
RAILS_ENVと呼ばれる環境を切り替えるための環境変数が用意されています. 最初はこれだけでも十分ですが開発が進むと環境毎に切り替えるプロジェクトがよくあるので備忘録として自分がよくやる対応をまとめてみました.config_for
config/database.ymlの様に環境毎で切り替える設定はconfig_forというメソッドがあるのでこれを使うとスッキリ書けます.Rails6 であれば、
sharedでマージされるのでデフォルト値が手軽に設定できます.Rails5を使ってるのであれば、YAMLのAnchors and Aliasesを使ってマージすると便利です.
# config/application.rb module MyApp class Application < Rails::Application config.foo = config_for(:foo).deep_symbolize_keys end end ### ruby Rails.configuration.foo[:key1] # => default Rails.configuration.foo[:key2].gsub('%{user_cd}', 'dummy1') # => hello dummy1 Rails.configuration.foo[:key3] # => shared value # if Rails6 # => nil # if Rails5設定より規約を活用して設定を減らす
普通にconfig_forを使ってるとYAMLの設定ファイルの運用が進むにつれて数が増えてきます.
もしくは、既存のシステムがあるとすれば既に膨大な設定になってるかと思います.
そこで設定より規約を使って最初から規約寄りにしておいた方が良いでしょう.
YAMLでは値に
key1: nullとあるとNULL値(Rubyだとnil)になります.key1: 'null'の様にクォートで囲むと文字列の"null"になります.これを利用して以下の様にしていきます.
# config/application.rb module MyApp class Application < Rails::Application config.foo = config_for(:foo).deep_symbolize_keys end end ### something ruby implements def config_foo_key1 "${Rails.configuration.foo[:key1] || 'default'}" endconfig_foo_key1の様に実装側にデフォルト値を用意することで、YAMLの設定ファイル自体がコンパクトになります.baseやsharedにデフォルト値を寄せても良いと思います.このケースの良いところは全ての環境が規約だけで運用できる様になった時、YAMLファイルが不要になるところにあります. 既存のハードコードされた設定があるのであれば、これらの方法を使って減らしていくと良いと思います.
bundle exec rails runner -e development 'puts config_foo_key1'default'MY_APP_KEY1=foo bundle exec rails runner -e production 'puts config_foo_key1'foo'環境変数にも規約をつける
アプリで固有で使う環境変数にも
MY_APP_KEY1の様に接頭辞MY_APP_の様に規約をつけると良いでしょう.grepした時に探すのも楽になるし、直感的にアプリ固有の環境変数だということがわかります.
環境毎にユニークな名前空間を使う
ここでの名前空間は以下の様なものを指しています.
AWS S3のバケット名通常、プロダクション環境だと、複数環境が相乗りになることは無いはずですが、デモ環境や開発環境は複数環境が相乗りになることがあります.
含める変数
Railsでは 環境変数
RAILS_ENVがあるし、parallel_tests ではENV['TEST_ENV_NUMBER']を使って並列に動作できるようにしています. さらにアプリ固有の環境変数もある場合もあります.これらを含めた名前空間にすることで開発環境の様に
developmentとtestが同じPCで動かせる様になります.例えばS3のオブジェクトのキーを考えてみましょう. 環境変数とデモ環境などの実際に動作する物理的な環境であれば
MY_APP_ENVの値にはdemo,prd,stg,qaそしてdevの様な値が入るとします.名前空間は
"#{Rails.env}#{ENV['TEST_ENV_NUMBER']}/${ENV['MY_APP_ENV']}"の様な規約にしておきます.これらの変数の組み合わせが展開されると以下の様になります. 名前空間が重なってないため柔軟に同じサーバや開発環境内に同居できる様になります.
development/devproduction/demoproduction/prdproduction/stgproduction/qatest/devtest2/dev