ActionText::Attachableのメソッド可視性をpublicに変更
ActionText::Attachable#read_attribute_for_serialization メソッドがpublicに変更されました。これにより、active_model_serializers を使用したシリアライズ時のエラーが解消されます。
背景
ActionText::Attachable は read_attribute_for_serialization をprivateメソッドとしてオーバーライドしていました。しかし、#49272 以降、元となる ActiveModel::Serialization#read_attribute_for_serialization が #53042 でpublicメソッドに変更されています。
この可視性の不一致により、active_model_serializers でモデルをシリアライズする際に「privateメソッドを呼び出した」というエラーが発生していました。rails-api/active_model_serializers#2457 で報告された問題です。
外部ライブラリが期待するpublicインターフェースとの整合性が失われたことが、この問題の原因でした。
技術的な変更
actiontext/lib/action_text/attachable.rb で read_attribute_for_serialization メソッドの定義位置が変更され、可視性がpublicになりました。
変更前:
private
def attribute_names_for_serialization
super + ["attachable_sgid"]
end
def read_attribute_for_serialization(key)
if key == "attachable_sgid"
persisted? ? super : nil
else
super
end
end
変更後:
# See ActiveModel::Serialization#read_attribute_for_serialization.
def read_attribute_for_serialization(key)
if key == "attachable_sgid"
persisted? ? super : nil
else
super
end
end
private
def attribute_names_for_serialization
super + ["attachable_sgid"]
end
メソッド定義が private 宣言の外に移動され、ドキュメントコメントが追加されています。メソッドの実装内容は変更されていません。
テストでは、メソッドが外部から呼び出せることを確認するケースが追加されました:
test "read_attribute_for_serialization returns the attribute" do
attachable = ActiveStorage::Blob.create_after_unfurling!(io: StringIO.new("test"), filename: "test.txt", key: 123)
assert_equal(attachable.key, attachable.read_attribute_for_serialization(:key))
end
設計判断
オーバーライドするメソッドの可視性に合わせる方針 が採用されました。
ActiveModel::Serialization のドキュメントは read_attribute_for_serialization をカスタマイズポイントとして明示的に言及しており、#53042 でpublicに昇格された経緯があります。Rails内部でのみ使用されるメソッドではなく、外部ライブラリが依存する可能性のあるインターフェースとして位置づけられています。
ActionText::Attachable がこのメソッドをprivateとしてオーバーライドすることは、親クラスのインターフェース設計と矛盾していました。可視性を揃えることで、Liskov置換原則に従った設計になっています。
まとめ
本PRは、親クラスの可視性変更に追従してメソッドをpublicに変更した修正です。メソッドの実装を変えずに定義位置のみを移動することで、active_model_serializers などの外部ライブラリとの互換性を回復しています。オーバーライドする側がインターフェース設計に従うという、オブジェクト指向の基本原則に沿った対応といえます。