`dependent: :purge` が期待通りにレコード削除時のファイルを完全削除するよう修正

rails/rails

Active Storage で dependent: :purge を指定しても添付ファイルが削除されずデタッチのみ行われていたバグを修正しました。これにより dependent: :purge / :purge_later / :detach の3つのオプションがすべて期待通りに動作するようになります。

背景

has_one_attached / has_many_attacheddependent オプションが一部のケースで期待通りに動作しないバグが #36423 で報告されていました。Active Storage では添付ファイルの削除方法として purge(同期削除)、purge_later(非同期削除)、detach(レコードのみ削除、ファイルは残す)の3種類が提供されています。

問題は dependent: :purge を指定した場合に発生していました。ユーザーレコードを削除すると、添付ファイルはストレージから削除されず「デタッチ」のみが行われていました。つまり ActiveStorage::Attachment レコードは消えてもファイル本体(ActiveStorage::Blob)はストレージに残留するという状態です。

Issue の指摘によると、問題の根本は lib/active_storage/attached/macros.rb のコールバック定義にあり、dependent: :purge_later の場合のみ after_destroy_commitpurge_later を呼び出し、それ以外はすべて before_destroydetach を呼び出す実装になっていたため、:purge:detach と同じ挙動になっていました。

技術的な変更

修正の核心は ActiveStorage::Attachment モデルの after_destroy_commit コールバックにあります。purge_dependent_blob_later というメソッド名と実装が :purge_later 専用になっていたものを、:purge もハンドリングできるよう拡張しました。

変更前:

after_destroy_commit :purge_dependent_blob_later

def purge_dependent_blob_later
  blob&.purge_later if dependent == :purge_later
end

変更後:

after_destroy_commit :purge_dependent_blob

def purge_dependent_blob
  if dependent == :purge_later
    blob&.purge_later
  elsif dependent == :purge
    blob&.purge
  end
end

コールバックメソッド名も purge_dependent_blob_later から purge_dependent_blob に改名され、役割がより正確に表現されています。dependent == :detachdependent == false の場合は条件に合致しないためファイルは削除されず、デタッチのみが呼び出し元の処理に委ねられます。

テストフィクスチャには dependent: :purge を指定した新たなアタッチメント定義が追加されました。

has_one_attached :icon, dependent: :purge
has_many_attached :favorites, dependent: :purge

これらを用いたテストケースがそれぞれ追加されており、レコード削除後に ActiveStorage::Blob レコードとストレージ上のファイルの両方が存在しないことを検証しています。

設計判断

after_destroy_commit コールバックに処理を集約する方式が採用されました。修正前のコードは before_destroy + after_destroy_commit に処理が分散していましたが、このPRでは after_destroy_commit 側の purge_dependent_blob メソッドで全ての dependent パターンを一元的に判定するよう整理されています。

メソッドの改名(purge_dependent_blob_laterpurge_dependent_blob)も重要な変更です。旧名称は「後で削除する」という意味を示唆していましたが、同期削除(:purge)も扱うようになったため、名称が実態とずれていました。新名称はモードに依存しない汎用的な表現になっています。

まとめ

本PRは1つのプライベートメソッドへの条件分岐追加という最小限の変更で、dependent: :purge / :purge_later / :detach の3オプションが設計通りに動作することを保証しました。メソッドの改名も合わせて行われ、コードの意図がより明確になっています。dependent: :purge を利用していたアプリケーションは、このバグ修正によりレコード削除時に添付ファイルが期待通りストレージから同期削除されるようになります。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
d3573d72

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文(総論)→背景・技術詳細・設計判断(各論)→まとめ(結論)という「総論→各論→結論」の3部構成が明確に守られており、非常に分かりやすい構成です。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きシンタックスハイライト(```ruby:filepath)とGitHubのPR/Issueリンク記法が正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

「Active Storage」「dependent」「purge」などの専門用語を前提としており、対象読者である専門知識を持つエンジニアにとって冗長な説明がなく適切です。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションが総論から各論への構成になっており、各パラグラフもトピックセンテンスで始まるなど、パラグラフ・ライティングの原則が遵守されています。これにより、記事の要点を素早く把握できます。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内で引用されている`activestorage/app/models/active_storage/attachment.rb`と`activestorage/test/test_helper.rb`のコードは、提供されたDiffの内容と完全に一致しています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`:purge`, `:purge_later`, `:detach`, `after_destroy_commit`などのActive Storage関連の技術用語が正確かつ文脈に沿って適切に使用されています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

「:purgeが:detachとして動作していた」という問題の説明や、「after_destroy_commitで:purgeもハンドリングする」という修正内容の説明は、PRのDescriptionおよびDiffのコード変更と整合性が取れており、技術的に正確です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内の主張はすべてPRのDescription、Diff、Issue情報に基づいており、根拠のない推測や創作(ハルシネーション)は見られません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#36433)および関連Issue番号(#36423)が正確に記載され、正しくリンクされています。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトル「`dependent: :purge` が期待通りにレコード削除時のファイルを完全削除するよう修正」は、PRのタイトル「Fix unexpected behavior for dependent: :purge」の内容をより具体的に、かつ正確に要約しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

記事内には、PR情報に基づかないバージョンサポート情報やリリース日程などの外部知識は含まれていません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

記事内の時間表現は事実に基づいており、「近い将来」や「まもなく」といったPR情報と矛盾するような歪曲は見られません。