Closed2

[Rails 6.0 → 6.1のメモ] ActiveModel::Errorsの挙動変化

nasanasa

ActiveModel::Errorsの挙動変化

ActiveModel::Errorsの挙動が変わっておりいくつかテストが落ちていた。
何が変わっているのか調べたのでメモとして残す。

nasanasa

該当コード: https://github.com/rails/rails/compare/v6.0.4.4...v6.1.4.4

以下のコードでvalidation errorに情報を付与していました。
Rails 6.0ではActiveModel::Erros#detailsメソッドは@detailsインスタンスへのアクセサとして定義されており、次のコードの3行目でエラー情報を追加する際に@detailsインスタンスが書き換わっていました。

hoge.errors.details.each do |attribute, details|
  details.each do |detail|
    detail[:hoge] = :fuga # これで上書きできていた
  end
end

しかしRails 6.1からはActiveModel::Errors#detailsが返すHash (正確にはDeprecationHandlingDetailsHashクラス)を更新しても内部状態が変わらなくなってしまいました。(これにより一部テストが落ちていました。テストで気づけてよかったー)

hoge.errors.details.each do |attribute, details|
  details.each do |detail|
    detail[:hoge] = :fuga # 変化しなくなった
  end
end

Railsのコードを見ると次のようなコメントが有り、後方互換性のためにこの挙動は残すと書いてありますが、挙動とのズレを感じますね、、、

# Updating this hash would still update errors state for backward
# compatibility, but this behavior is deprecated.

ref: https://github.com/rails/rails/blob/87d4d0f4126f64d991d40a1827de50935ddfdbff/activemodel/lib/active_model/errors.rb#L346

optionsというフィールドを更新することでコンテキストを付与することができるのでそちらを使い解決しました。

error.options.store(:hoge, :fuga)
このスクラップは2023/01/28にクローズされました