LoginSignup
5
1

new_framework_defaults_x_xを更新しても、値が反映されないことがあるので注意

Last updated at Posted at 2024-02-27

Railsのアップデートの際に、新しいバージョンの config のデフォルト値を少しずつ反映させるときに new_framework_defaults_x_x を使うと思います。

今回、config.load_defaults 6.1 へ上げる前に、Rails.application.config.active_record.has_many_inversing = trueの設定をしても反映されないことがありました。

たまたま今回は has_many_inversing でハマりましたが、他の設定でも同様ですし、new_framework_defaults 以外の config/initializers/* での設定も同様にRails.application.config.xxxの設定が反映されない可能性があるので記事にしてみました。

結論

初期化時の読み込み順によっては、config/initializers/* のファイルの設定値が反映されないことがあるので、 その場合はconfig/application.rbなどのRails.application.initialize!を実行する前に設定する必要があるようです。

RailsにもIssueとして上がっていました。

少し解説

今回、具体的な原因特定はできていないので、詳しくは上記のIssueを確認してください

Rails v6.1の実装の話をしますが、v7.0では少し変わっています

Rails.application.config.active_record.has_many_inversing に値をセットすることで、ActiveRecord::Base.has_many_inversingに値をセットすることができます。

ActiveRecord::Base.has_many_inversingは内部でinvertible かの判定に使われています1

今回、以下のように設定したのですが、

config/initializers/new_framework_defaults_6_1.rb
Rails.application.config.active_record.has_many_inversing = true

以下のように、ActiveRecord::Base.has_many_inversingには値が反映されていませんでした。

[1] > Rails.application.config.active_record.has_many_inversing
=> true
[2] > ActiveRecord::Base.has_many_inversing
=> false

ちなみに、 config/application.rb に記述したところ、反映されていました。

config/application.rb
Module Hoge
  class Application < Rails::Application
    # ...
    config.active_record.has_many_inversing = true
    # ...
  end
end

調査をしたこと

ActiveRecord::Base.has_many_inversingのgetterは以下で定義されています。

module ActiveRecord
  module Core
    extend ActiveSupport::Concern

    included do
      # ...
      mattr_accessor :has_many_inversing, instance_accessor: false, default: false

値をセットしているところを確認すると、以下のようになっていました。

    initializer "active_record.set_configs" do |app|
      ActiveSupport.on_load(:active_record) do
        configs = app.config.active_record

        configs.each do |k, v|
          send "#{k}=", v
        end
      end
    end

ActiveSupport.on_load(:active_record)のフックは、 ActiveRecord がロードされると実行されるようです。

この処理が実行されるタイミングにログを仕込んでみたところ、初期化処理のload_config_initializersのタイミングよりも早くに実行されていることがわかりました。

おそらく、どれかのgemなどで ActiveRecord が読み込まれているのだと思われます。

今後

Rails側で、読み込みのタイミングにかかわらず、initializersで設定した内容が反映されるようになるといいですが、それまでは注意して確認する必要があります。
反映されない場合は config/application.rbの初期化実行前にセットする必要があります。

config/initializersでセットした内容が反映されないこともあるというのが盲点でもしかしたら他にもハマる人がいるかもしれないので、助けになると嬉しいです。

関連

  1. https://github.com/rails/rails/pull/37429

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1