Empty filter case of ParameterFilter#filter returns a duplicate
ActiveSupport::ParameterFilter の #filter がフィルターなしで呼び出されたとき、元のパラメータハッシュと等価だが同一オブジェクトではない dup を返すことを保証するテストが追加されました。
背景
このテストは ActiveSupport::ParameterFilter#filter が空フィルターの場合に速いパスで params.dup を返す実装を持つことは既にコード上にあるものの、実際の挙動を検証するテストが欠如していた点を補完します。従来は filter_param に対してのみ空フィルター時の動作がテストされており、#filter の同様のケースは未確認でした。
そのため、将来的なリファクタリングで速いパスが削除されたり動作が変わったりするリスクを低減する目的で、明示的なテストが導入されました。
技術的な変更
activesupport/test/parameter_filter_test.rb に以下のテストが新規追加されました。
test "filter with empty filters returns a dup of the params" do
parameter_filter = ActiveSupport::ParameterFilter.new
original = { "foo" => "bar" }
filtered = parameter_filter.filter(original)
assert_equal original, filtered
assert_not_same original, filtered
end
テストは フィルターが無い ActiveSupport::ParameterFilter.new を生成し、単純なハッシュ { "foo" => "bar" } を filter に渡します。その結果が内容的に同一(assert_equal)であることと、オブジェクトとしては別物(assert_not_same)であることを確認します。実装側では filter が @no_filters ? params.dup : call(params) という条件式で速いパスを選択しており、この挙動がテストで裏付けられます。
この変更は本番コードに影響を与えず、テストスイートの網羅性を高めるだけです。
設計判断
#filter が dup を返す ことをテストで明文化することで、API が「引数を変更しない」ことを保証する設計方針が強化されます。将来的に内部実装が変わり、直接ハッシュを返すようになるとこのテストが失敗し、非意図的なミュータブル動作の導入を防止します。
このアプローチは、実装上の最適化(速いパス)と外部からの不変性保証という二つの観点を同時に満たす設計判断と言えるでしょう。
まとめ
テストのみの追加ですが、ActiveSupport::ParameterFilter#filter が空フィルター時に 新しいオブジェクト を返すことを明確に検証します。これにより、パラメータの不変性という重要な契約が保証され、将来の実装変更に対して安全性が向上します。