3行まとめ
- Rails 7.1 から
dup
,freeze
,hash
,object_id
,class
,clone
,frozen
は column 名や enum の種類として使えなくなる可能性が高い - 該当 column を持つ Model の initialize で
ActiveRecord::DangerousAttributeError
が発生する - 各位そういった名前を使わない、rename するなど身構えておきましょう
起きていた問題
会社の Rails アプリケーションに対して rails/rails の main branch を使ってテストを走らせていたら以下のようなエラーを数多く見かけるようになった。
ActiveRecord::DangerousAttributeError: object_id is defined by Active Record. Check to make sure that you don't have an attribute or method with the same name. # /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/decorator/new_constructor.rb:9:in `new' # /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/decorator.rb:16:in `send' ...
どうやらテストの前準備のレコード作成でコケている様子。(具体的には factory_bot の create(:xxxx)
)
object_id...?なんのことだ...?と思って調べてたら作成対象の model の association に object_id という column を持つ model が存在することが分かった。 ActiveRecord によって object_id メソッドを上書きされるの危険そうだなと思いつつ、なぜ Rails 7.0 ではエラーにならず Rails 7.1 で問題になるのか分からなかったので調べてみて原因を特定した。
変更が入ったのは上記 PR。column 名に hash
という名前を使うと ActiveRecord が Object#hash
をオーバーライドしてしまい、問題が発生していた。
その問題と今後発生しそうな問題を防ぐために Object クラスでオーバーライドされると困りやすい dup
, freeze
, hash
, object_id
, class
, clone
を AR が定義しようとするとエラーにする変更を加えたとのこと。
後続の変更で frozen?
も使えなくなっている。AR は boolean の column に対しては自動的に ?
付きのメソッドを定義するので boolean の frozen column も使えなくなってそう。
これは column だけではなく enum によるメソッド定義でも同様なので enum の種類に frozen を使っているアプリケーションも書き換えが必要になるんじゃないかな。
まだ Rails 7.1 はリリースされていないので確定ではないものの、主張としては真っ当なのでそのまま入りそうな気がしている。 上記に該当するアプリケーションをお持ちの方は身構えておくと良いのではないでしょうか。
感想
git bisect コマンド初めて使ったんですが、これ便利ですね...