2
0

Rails7.1.3 での table_name_prefix の挙動の違い

Last updated at Posted at 2024-02-18

Rails7.1.3へのアップデート

Rails7.1.3のアップデートの際に思わぬところで躓いたので共有です
Rails7.1.3で適用された、このPRについてです

対象読者

  • Rails エンジンで table_name_prefix を自分で定義している人

さきに結論

  • blorghというエンジンがあったとして lib/blorgh.rbtable_name_prefixを上書きしていた場合、Rails 7.1.3で効かなくなった
  • isolate_namespaceの呼び出し前に、Blorghモジュールでtable_name_prefixを上書きする

状況

Rails7.1.2 までの環境

Railsエンジン側でモデルを用意しており、table_name_prefixを定義していたとします

blorghというエンジンだとすると、下記のような感じ

lib/blorgh.rb
require "blorgh/version"
require "blorgh/engine"

module Blorgh
  def self.table_name_prefix
    "custom_blorgh_"
  end
end
lib/blorgh/engine.rb
module Blorgh
  class Engine < ::Rails::Engine
    isolate_namespace Blorgh
  end
end

Blorgh::Userモデルを定義すると、テーブル名は以下のようになります

❯ bin/rails console
Loading development environment (Rails 7.1.2)
irb(main):001> Blorgh::User.table_name
=> "custom_blorgh_users"

Rails 7.1.3 にアップデートします

アップデート後、テーブル名を確認してみます

❯ bin/rails console
Loading development environment (Rails 7.1.3)
irb(main):001> Blorgh::User.table_name
=> "blorgh_users"

なんと、、、 プレフィックスが外れています

Rails7.1.3でマージされた Make isolated engines aware of ActiveRecord::Base table name prefix by chaadow の中で、新たに処理が追加されています

PRで変更が入ったRails::Engine#isolate_namespaceの実装を見てみます

engine.rb
unless mod.respond_to?(:table_name_prefix)
  define_method(:table_name_prefix) { "#{name}_" }

  ActiveSupport.on_load(:active_record) do
    mod.singleton_class.redefine_method(:table_name_prefix) do
      "#{ActiveRecord::Base.table_name_prefix}#{name}_"
    end
  end
end

https://github.com/rails/rails/blob/v7.1.3/railties/lib/rails/engine.rb#L400-L404

つまり、rails engineのmoduleにtable_name_prefixメソッドが定義されてなければ、再定義するようになっています

対応

なので、Rails::Engine#isolate_namespaceの意図を汲み取りつつ、isolate_namespaceを呼ぶ前にtable_name_prefixを定義してみます

lib/blorgh.rb
require "blorgh/version"
require "blorgh/engine"

module Blorgh
-  def self.table_name_prefix
-    "custom_blorgh_"
-  end
end
lib/blorgh/engine.rb
module Blorgh
+  def self.table_name_prefix
+    "custom_blorgh_"
+  end

  class Engine < ::Rails::Engine
    isolate_namespace Blorgh
  end
end

とすると、

❯ bin/rails console
Loading development environment (Rails 7.1.3)
irb(main):001> Blorgh::Admin.table_name
=> "custom_blorgh_admins"

プレフィックスがちゃんとつきました

Railsのテストを参考)https://github.com/rails/rails/blob/main/railties/test/railties/engine_test.rb#L1283

もちろん、下記のように application_record.rbに定義して、継承する形でも問題ないでしょう

models/blorgh/application_record.rb
module Blorgh
  def self.table_name_prefix
    "custom_blorgh_"
  end

  class ApplicationRecord < ActiveRecord::Base
    self.abstract_class = true
  end
end

Railsのテストモデルを参考) https://github.com/rails/rails/blob/main/activerecord/test/models/company_in_module.rb#L34

まとめ

  • blorghというエンジンがあったとして lib/blorgh.rbtable_name_prefixを上書きしていた場合、Rails 7.1.3で効かなくなった
  • isolate_namespaceの呼び出し前に、Blorghモジュールでtable_name_prefixを上書きする

何気ないパッチアップデートでも引っかかったので、Railsのバージョンアップはやはり注意してみないといけないですね

2
0
1

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
2
0