Railsの初期化コードと置き場所

Railsでconfig配下に置く各種初期化ファイルについて、それぞれのユースケースや実行の順番について整理しておきます。

今回はRailsガイドでも挙げられている、代表的な初期化コードの配置および定義場所を扱います。

  • config/application.rb
  • config/environments 配下
  • config/initializers 配下
  • initialization events

config/application.rb

Railsアプリケーションの起動時にgemなどに依存しない、1番はじめに実行させたい共通の初期化コードを書きます。

Rails::ApplicationはRails::Railtieを間接的に継承しているため、config/application.rbでinitializerメソッドを使用して、アプリケーションの初期化処理を定義することができます。

config/environments 配下

環境毎の初期化コードが書かれた設定ファイルを置きます。 例えば、config/environments/production.rbなどが該当します。

config.active_storage.serviceを、環境毎に:local:amazonなどに変更するような使い方をイメージするとよいです。

config/initializers 配下

環境にかかわらず共通で行う初期化コードが書かれた設定ファイルを置きます。 gemやRailsフレームワークで使用する初期化コードが置かれることが多いです。

initialization events

Rails::Application, Rails::Railtie, Rails::Engineのサブクラスで使用可能な初期化時のイベントフックが5つ存在します。

  • before_configuration
  • before_initialize
  • to_prepare
  • before_eager_load
  • after_initialize

after_initialize 使用されることが多いイベントフックで - Railsアプリケーション(フレームワーク)の初期化が完了した後の初期化コード - gemに依存する初期化コード などを書きます。

実行の順番

実行の順番についてまとめておくとそれぞれ、以下となります。

初期化の順番

  1. config/application.rb
  2. config/environments 配下
  3. config/initializers 配下

また、config/initializers配下のファイルの読み込みの順番はアルファベットや数字の並び順にファイルが読み込まれるため、01,02のようなプレフィックスをファイル名につけることで、実行の順番を保証することができます。

初期化イベントの呼び出される順番

  • initialization events
    1. config/application.rbに定義
    2. config/environments 配下に定義
    3. config/initializers 配下に定義

実際に動かしてみる

実際に各初期化ファイルやコードがどの順番で実行されているかも確認しておきます。 開発者モード(RAILS_ENV=development)で検証しています。

config/application.rb

class Application < Rails::Application
    ...
    puts "config/application.rb"
    ...
end

config/environments/development.rb

Rails.application.configure do
    ...
  puts "config/environments/development.rb"
  ...
end

config/initializers/application_controller_renderer.rb

...
puts "config/initializers/application_controller_renderer.rb"
...

config/initializers/mime_types.rb

...
puts "config/initializers/mime_types.rb"
...

結果

config/application.rb
config/environments/development.rb
config/initializers/application_controller_renderer.rb
config/initializers/mime_types.rb

上記に加えて、各ファイルでafter_initializeを定義してみます。

config/application.rb

class Application < Rails::Application
    ...
    puts "config/application.rb"

    Rails.application.config.after_initialize do
        puts "config/application.rb | after_initialize"
    end
    ...
end

config/environments/development.rb

Rails.application.configure do
    ...
  puts "config/environments/development.rb"

    Rails.application.config.after_initialize do
        puts "config/environments/development.rb | after_initialize"
    end
  ...
end

config/initializers/application_controller_renderer.rb

...
puts "config/initializers/application_controller_renderer.rb"

Rails.application.config.after_initialize do  
  puts 'config/initializers/application_controller_renderer.rb | after_initialize'  
end
...

結果

config/application.rb
config/environments/development.rb
config/initializers/application_controller_renderer.rb
config/initializers/mime_types.rb
↓after_initialize↓
config/application.rb | after_initialize
config/environments/development.rb | after_initialize
config/initializers/cors.rb | after_initialize

Config gemを使う場合の注意

ここからは番外編です。 定数値を管理するためにConfig gemがよく使用されるかと思いますが、gem側で初期化のタイミングを必ず一番はじめに強制する挙動があるため注意が必要です。

特に、Config gemの初期化の前に、Rails.applicationの初期化に依存する事前処理を行いたい場合に考慮が必要となります。 initialization eventsのbefore_configurationを使用したとしても、対象の処理をConfig gemの初期化処理よりも前に持ってくることができません。

これは、Config gemがRails::Railtie継承したクラス内で、before_configurationを定義することで初期化のタイミングをトップレベルに持ってきていることによる挙動となります。

そのため、config/initializers/config.rbの初期化ブロックの一番最初の処理として、Rails.applicationの初期化に依存する処理を書くことになります。

Config.setup do |config|
    Rails.application...
    ...
end

参考

https://guides.rubyonrails.org/initialization.html https://guides.rubyonrails.org/configuring.html https://github.com/rubyconfig/config/blob/master/lib/config/integrations/rails/railtie.rb