Proc と Regexp の filter_attributes を filter_parameters への同期から除外
Rails 8.1 で ActiveRecord::FilterAttributeHandler がモデルの filter_attributes を Rails.application.config.filter_parameters に同期する際、Proc と Regexp が文字列化されて不要なエントリが生成されていました。この PR はそれらを除外し、設定配列の安定性と可読性を向上させます。
背景
filter_attributes はシンボル・文字列に加えて Proc と Regexp も受け取りますが、同期処理が全要素を to_s で文字列化していたため、"user.#<Proc:0x...>" や "user.(?i-mx:secret)" といった実行不可能なフィルタが filter_parameters に蓄積されました。これらはログフォーマッタや診断ツールに露出し、ブートごとにオブジェクト ID が変わるため配列が不安定になるという実務上の問題がありました。
その結果、パラメータロギングで本来のフィルタ以外のゴミが増えるだけでなく、 Proc の文字列表現が含まれることで設定が読みにくくなっていました。
技術的な変更
apply_filter メソッドに型チェックを導入し、Symbol と String のみ を filter_parameters へ同期するよう変更しました。具体的には case 文で属性の型を判定し、対象外の型はスキップします。
変更前:
klass_name = klass.name ? klass.model_name.element : nil
filter = [klass_name, attribute.to_s].compact.join(".")
app.config.filter_parameters << filter unless app.config.filter_parameters.include?(filter)
変更後:
case attribute
when Symbol, String
klass_name = klass.name ? klass.model_name.element : nil
filter = [klass_name, attribute.to_s].compact.join(".")
app.config.filter_parameters << filter unless app.config.filter_parameters.include?(filter)
end
この変更に伴い、railties/test/application/active_record_railtie_test.rb にテストが追加され、Proc と Regexp が filter_parameters に混入しないことを自動的に検証しています。
テスト例:
class Post < ActiveRecord::Base
self.table_name = "posts"
self.filter_attributes += [:special_attr, /secret/i, ->(key, value) { value.reverse! }]
end
assert_includes Rails.application.config.filter_parameters, "post.special_attr"
garbage = Rails.application.config.filter_parameters.grep(String).select do |filter|
filter.include?("#<Proc") || filter.include?("(?i-mx:")
end
assert_empty garbage
設計判断
apply_filter で 型限定 を行う実装は、既存の filter_attributes API を変更せずに問題を解決する保守的な選択です。Proc と Regexp は依然として ActiveSupport::ParameterFilter によってグローバルに機能しますが、文字列化して filter_parameters に流す必要がなくなったため、設定配列の 安定性 と 可読性 が向上しました。
このアプローチは、追加の設定キーやオプションフラグを導入する代わりに、既存コードパスに最小限の分岐を加えることで後方互換性を保ちつつ、実装上のゴミデータ生成を防いでいます。
まとめ
apply_filter がシンボルと文字列のみを filter_parameters に同期するよう変更されたことで、Proc と Regexp に起因する不要な文字列エントリが除去され、設定配列の安定性と可読性が向上しました。既存のフィルタ機構はそのまま維持され、Rails アプリ全体のロギング設定がクリーンになる効果があります。