ActionTextの削除済み添付ファイルをプレーンテキストでも「☒」として表示

rails/rails

ActionTextでは、削除済み添付ファイルを to_plain_text で変換する際に、HTML表示と同じ「☒」記号が表示されるようになりました。これにより、HTML・プレーンテキスト・Markdownの全形式で、欠落した添付ファイルの表現が統一されます。

背景

ActionTextでは、削除済みまたは見つからない添付ファイルを MissingAttachable クラスで表現します。HTML形式では「☒」(U+2612、BALLOT BOX WITH X)記号を使って壊れた添付ファイルを示していましたが、Content#to_plain_text を使用した場合は空文字列に置き換えられていました。

この非対称性は、MissingAttachableattachable_plain_text_representation メソッドを実装していなかったことに起因します。HTML表示とプレーンテキスト表示で異なる挙動となり、削除済み添付ファイルの存在が見えなくなる問題がありました。

技術的な変更

actiontext/lib/action_text/attachables/missing_attachable.rbattachable_plain_text_representation メソッドが追加されました。

変更後:

def attachable_plain_text_representation(caption = nil)
  "☒"
end

このメソッドは、既存の attachable_markdown_representation と同じ「☒」文字を返します。HTML部分テンプレートで使用される記号と統一されることで、すべての出力形式で一貫した表現が得られます。

テストケースも追加され、削除済み添付ファイルが正しく「☒」として変換されることが検証されています:

test "converts missing attachables to plain text" do
  file = create_file_blob(filename: "racecar.jpg", content_type: "image/jpeg")
  html = %Q(<action-text-attachment sgid="#{file.attachable_sgid}"></action-text-attachment>)
  file.destroy!
  content = content_from_html(html)

  assert_equal "☒", content.to_plain_text
end

設計判断

既存のMarkdown変換との整合性を重視した設計 が採用されました。

MissingAttachable は既に attachable_markdown_representation で「☒」を返していたため、attachable_plain_text_representation も同じ記号を返すことで、出力形式間の一貫性が保たれています。引数の caption を受け取るシグネチャも既存メソッドと揃えられていますが、実装では使用されていません。

PR内の補足情報では、<action-text-attachment> ノードに urlcontent-type 属性が残っている画像添付ファイルは RemoteImage として解決され、プレーンテキストでは [Image] と表示されることが説明されています。MissingAttachable として扱われるのは、バッキングレコードが完全に失われたケースのみです。この明確な区別により、異なる種類の「見つからない」状態が適切に表現されます。

まとめ

本PRは、ActionTextの出力形式間で削除済み添付ファイルの表現を統一した変更です。attachable_plain_text_representation メソッドの追加により、HTML・プレーンテキスト・Markdownの全形式で「☒」記号が使用されるようになり、ユーザーは出力形式に関わらず壊れた添付ファイルの存在を認識できるようになりました。

記事メタデータ

Generated by:
Claude Sonnet 4.5 for DiffDaily

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

品質レビュー結果

Review Status:
リトライ後承認
Review Count:
2回 (改善を経て承認)
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

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

「リード文(総論)→背景・技術詳細・設計判断(各論)→まとめ(結論)」という3部構成が明確に適用されています。各セクションの役割が明確で、非常に分かりやすい構成です。

カスタムMarkdown構文 ✓ PASS

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

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

対象読者への適合性 ✓ PASS

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

ActionTextの内部実装に関する内容であり、専門知識を持つエンジニアという対象読者に適した技術レベルと表現で書かれています。

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

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

各セクションが総論→各論で構成され、各段落がトピックセンテンスで始まっています。1段落1トピックの原則と適切な段落長も守られており、可読性が高いです。

Diff内容との照合 ✓ PASS

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

記事内で引用されている2つのコードブロック(`missing_attachable.rb`と`content_test.rb`)は、提供されたDiffの内容と完全に一致しており、ファイル名も正確です。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`MissingAttachable`, `attachable_plain_text_representation`, `RemoteImage`などの技術用語が、PRの文脈に沿って正確に使用されています。

説明の技術的正確性 ✓ PASS

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

「`attachable_plain_text_representation`が未実装だったため空文字列になっていた」という原因の説明や、`MissingAttachable`と`RemoteImage`の挙動の違いに関する説明は、PR情報に基づいており技術的に正確です。

事実の突合 ✓ PASS

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

記事内のすべての主張(変更前後の挙動、原因、設計意図など)は、PRのDescriptionやDiffによって裏付けられており、ハルシネーションは検出されませんでした。

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

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

PR番号(#56854)が正確に記載されています。

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

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

記事のタイトル「ActionTextの削除済み添付ファイルをプレーンテキストでも「☒」として表示」は、PRのタイトル「Render MissingAttachable as "☒" in plain text」の内容を的確に表現しています。

外部知識の正確性 ✓ PASS

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

バージョン情報やリリース予定など、PR情報に記載のない外部知識の追加はなく、提供された情報源に忠実です。

時間表現の正確性 ✓ PASS

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

「〜でした」「〜ようになりました」といった時間表現が、PRで示されている変更の前後関係(Previously/Now)を正しく反映しています。