/ #rails #ruby 

Railsで`config/x`みたいなディレクトリ作るとymlが分かりやすくなる説

こんにちは。この記事はRuby on Rails Advent Calendar 2021の23日目の記事です。 もう2日過ぎちゃってますが、この23日は誰も埋めていなかったようなので埋めてみました。

Railsでconfig/xみたいなディレクトリ作ってそこに config_for で読み込むymlを置くとスッキリして分かりやすくなるんじゃないか という思いがあり、それについて書きます。

TOC

  1. Railsで Rails.configurationconfig_for を活用する話
    • config.x.なんかconfig.なんか の違いとはなんなのか
  2. そうすると config/*.yml がいっぱいできるじゃん?
    • 見通しの悪さよ
  3. アイデア: アプリの独自設定は config/x/*.yml に置いたらいいのでは?


Railsで Rails.configurationconfig_for を活用する話


まず、Rails.configurationconfig_for についてです。

これはRails4.2から導入されたもので、それまでの config gem(懐かしい)や settings_logic gem (懐かしい)の代わりになるものでした

以下は最新7.0バージョンのrailsガイド(https://guides.rubyonrails.org/configuring.html#custom-configuration) からの抜粋です。

まず Rails.configuration

設定するときは config/application.rb などで

config.x.payment_processing.schedule = :daily
config.x.payment_processing.retries  = 3
config.super_debugger = true

呼び出すときは任意の場所で

Rails.configuration.x.payment_processing.schedule # => :daily
Rails.configuration.x.payment_processing.retries  # => 3
Rails.configuration.x.payment_processing.not_set  # => nil
Rails.configuration.super_debugger                # => true

のように使います。

次にconfig_for について

config_forはyamlを読み込むためのメソッドです。

Rails.configuration にセットするために使う例が多いです。

# config/payment.yml
production:
  environment: production
  merchant_id: production_merchant_id
  public_key:  production_public_key
  private_key: production_private_key

development:
  environment: sandbox
  merchant_id: development_merchant_id
  public_key:  development_public_key
  private_key: development_private_key

のようなyamlを配置し、config/application.rbconfig.なにか(またはconfig.x.なにか) にセットします。

# config/application.rb
module MyApp
  class Application < Rails::Application
    config.payment = config_for(:payment)
  end
end

↑ここではx を使わずに config.payment=とセットしているので、

呼び出すときは以下のように呼び出します。

Rails.configuration.payment['merchant_id'] # => production_merchant_id or development_merchant_id

x を挟んで config.x.payment= みたいにセットすることもできます。

# config/application.rb
module MyApp
  class Application < Rails::Application
    config.x.payment = config_for(:payment) # `x` を挟んだ
  end
end

この場合は呼び出すときも x を挟み、以下のような感じで取り出すことができます。

Rails.configuration.x.payment['merchant_id'] # => production_merchant_id or development_merchant_id

config.x.なんかconfig.なんか の違いとはなんなのか

実装上の話をすると、「ネストできる」のが config.x.なんか です。

# 例
config.x.payment_processing.schedule = :daily

今のrailsガイド的には、それ以外の意味はなさそうです。

が、なんとなく x と付けるのは、httpの独自ヘッダーみたいに、独自的・局所的な要素であることの印象を受けます(私だけでしょうか)

そうすると config/*.yml がいっぱいできるじゃん?


x を使っても使わなくてもどちらの場合でもそうなのですが、

以上のようなことを活用していくとconfig/の下がymlでいっぱいになります。

config/の下のファイルたちのイメージ:

application.rb
bar.yml
baz.yml
boot.rb
cable.yml
corge.yml
database.yml
environment.rb
environments/
foo.yml
fred.yml
garply.yml
grault.yml
initializers/
locales/
newrelic.yml
plugh.yml
puma.rb
quux.yml
qux.yml
routes.rb
sidekiq.yml
spring.rb
storage.yml
thud.yml
waldo.yml
webpack/
webpacker.yml

見通しの悪さよ


いっぱいになる分には良いのですが、

「(Railsを初めとした) config/の下に設定ファイルを置く規約にしているgemのyamlと区別がつかなくなってしまう」という問題があります。

具体的には、

  • config/cable.ymlconfig/database.yml が置いてあるが、これはRails由来。
  • config/sidekiq.yml は 3rd party gem(sidekiq gem)由来。
  • config/newrelic.yml は 3rd party gem(newrelic gem)由来。
  • それ以外の config/*.ymlconfig/applicaition.rb から config_for で呼んでいる

みたいな感じです。

つまりconfig/の下のファイルたちにコメントを付けると、以下のような感じです。

application.rb
bar.yml          # このrails app独自のもの
baz.yml          # このrails app独自のもの
boot.rb
cable.yml        # rails由来
corge.yml        # このrails app独自のもの
database.yml     # rails由来
environment.rb
environments/
foo.yml          # このrails app独自のもの
fred.yml         # このrails app独自のもの
garply.yml       # このrails app独自のもの
grault.yml       # このrails app独自のもの
initializers/
locales/
newrelic.yml     # newrelic gem由来
plugh.yml        # このrails app独自のもの
puma.rb
quux.yml         # このrails app独自のもの
qux.yml          # このrails app独自のもの
routes.rb
sidekiq.yml      # sidekiq gem由来
spring.rb
storage.yml      # rails由来
thud.yml         # このrails app独自のもの
waldo.yml        # このrails app独自のもの
webpack/
webpacker.yml    # rails由来

詳しい人が見ればわかるのですが、パッと見で分かりづらくなってしまいます。

アイデア: アプリの独自設定は config/x/*.yml に置いたらいいのでは?


そこで提案なんですが、

実は、config_for は 引数を調整することにより、config/ 以外を読むことができます! のでこれを活用したらいいと思います!

(rails5.0から変わりました。該当のコミット: https://github.com/rails/rails/commit/fc635b565393bd6b70be4af524934b3ea359e83c 。 )

これにより、config/application.rbは以下のように書き換えることができます。

# config/application.rb
module MyApp
  class Application < Rails::Application
    config.x.bar   = config_for(Rails.root.join('config/x/bar.yml'))
    config.x.baz   = config_for(Rails.root.join('config/x/baz.yml'))
    config.x.corge = config_for(Rails.root.join('config/x/corge.yml'))
    # ...snip...
    config.x.waldo = config_for(Rails.root.join('config/x/waldo.yml'))
  end
end

こうすることで、Railsや3rd party gemがconfig/の下に配置するymlと区別がつきやすくなります

config/の下のファイル。 イメージ:

# config/
application.rb
boot.rb
cable.yml        # rails由来
database.yml     # rails由来
environment.rb
environments/
initializers/
locales/
newrelic.yml     # newrelic gem由来
puma.rb
routes.rb
sidekiq.yml      # sidekiq gem由来
spring.rb
storage.yml      # rails由来
webpack/
webpacker.yml    # rails由来
x/

config/xの下のファイル。 イメージ:

# config/x/
bar.yml          # このrails app独自のもの
baz.yml          # このrails app独自のもの
corge.yml        # このrails app独自のもの
foo.yml          # このrails app独自のもの
fred.yml         # このrails app独自のもの
garply.yml       # このrails app独自のもの
grault.yml       # このrails app独自のもの
plugh.yml        # このrails app独自のもの
quux.yml         # このrails app独自のもの
qux.yml          # このrails app独自のもの
thud.yml         # このrails app独自のもの
waldo.yml        # このrails app独自のもの

このように分離されることにより、スッキリしますよね!

まとめ

このエントリでは、config/x のようなディレクトリを作りそこにymlファイルを置くことにより、設定用のymlファイルを整理する検討を行いました。

Author

hoshinotsuyoshi

星野剛志(ほしのつよし) web application engineer. ruby/rails/docker