はじめに
弊プロダクトではマルチテナントを実現出来る apartment gem を使っています(正確には本家は更新が止まっているので rails-on-services プロジェクトの ros-apartment)。
今回 apartment を 2.11.0、rails を 7.0.8 にアップデートした所遭遇したエラーとその対応について記します。
TL;DR
apartment は master ブランチのリリースが止まっているので development ブランチを使用する(自己責任において)。
gem 'ros-apartment', require: 'apartment', git: 'https://github.com/rails-on-services/apartment.git', branch: 'development'
ros-apartment について
オリジナルの apartment は開発が止まっており、それを受けてフォークして作られたリポジトリです。尚こちらもリリースが滞り気味です。
rails と apartment をバージョンアップしたところ `connected_to': unknown keyword: :database (ArgumentError)
エラーに遭遇しました。
調べてみると apartment が rails のメソッドに対して alias
でパッチを当てている部分の rails 側の変更によるエラーのようで、すでに PR が出ているのでそれを参考に以下のようにパッチを当てて対処しようとしました。
module MyApp
module ActiveRecord
module ConnectionHandling
def connected_to_with_tenant(role: nil, prevent_writes: false, &blk)
current_tenant = Apartment::Tenant.current
connected_to_without_tenant(role: role, prevent_writes: prevent_writes) do
Apartment::Tenant.switch!(current_tenant)
yield(blk)
end
end
alias connected_to_without_tenant connected_to
alias connected_to connected_to_with_tenant
end
end
end
しかしどうやっても新しく定義したメソッドが呼ばれず古いメソッドが呼ばれ続けてしまいました。
alias
で別名定義されたメソッドは上書きが出来ない
色々調べたところ、どうやら一度 alias
によって別名をつけられたメソッドはその後オーバーライドをしても再定義が出来ないという仕様のようで、alias
で別名が付けられたメソッドに対しては「別モジュールで同名メソッドを定義して prepend
で上書き」という方法は使えないようでした。
参考にさせていただいた記事
https://www.xmisao.com/2014/09/12/ruby-alias-tips.html
https://r7kamura.com/articles/2018-04-02-alias-prepend-f376914c93fb
というわけで ros-apartment の対処については冒頭のとおりですが、それとは別に alias
によって別名定義されたメソッドに関してはメソッド名自体を変更したり、呼び出し元をオーバーライドする必要があるという知見でした。