`request.safe_method?` と `request.unsafe_method?` の追加

rails/rails

ActionDispatch::Request に RFC 9110 §9.2.1 の命名規則に基づく safe_method?unsafe_method? の2つの述語メソッドが追加されました。これにより、コントローラやミドルウェアでリクエストの安全性を判定する際、標準的な語彙でコードを記述できるようになります。

背景

コントローラやミドルウェアでは「このリクエストはサーバー状態を変更しうるか」という判定が頻繁に必要になります。しかし、これまで Rails にはその判定を一言で表す標準的なメソッドがなく、get? || head? のような ad-hoc な条件式が各コールサイトに散在していました。

HTTP の仕様書である RFC 9110 §9.2.1 は、GET・HEAD・OPTIONS・TRACE を「安全なメソッド(safe methods)」と定義しています。本 PR はこの仕様の命名をそのまま Rails のインターフェースに取り込むことで、意図を明示した共通の語彙を提供します。

コードベース全体で get? || head? のような表現を統一する語彙を持つことは、レビュー時の可読性向上とバグの防止につながります。たとえば OPTIONS や TRACE を見落とした不完全な条件式も、safe_method? に置き換えることで正確な判定ができます。

技術的な変更

actionpack/lib/action_dispatch/http/request.rbbearer_token メソッドの直後に、2つのメソッドが追加されました。

# True if the request method is safe per RFC 9110 §9.2.1
# (GET, HEAD, OPTIONS, or TRACE).
def safe_method?
  get? || head? || options? || trace?
end

# True if the request method may modify resources. Inverse of #safe_method?.
def unsafe_method?
  !safe_method?
end

safe_method? は GET・HEAD・OPTIONS・TRACE の4メソッドを安全とみなし、既存の述語メソッドを組み合わせて実装されています。unsafe_method? はその単純な否定であり、POST・PUT・PATCH・DELETE などに対して true を返します。

テストは actionpack/test/dispatch/request_test.rbRequestSafety クラスとして追加されており、安全なメソッド群と安全でないメソッド群のそれぞれで両メソッドの真偽値を検証しています。

class RequestSafety < BaseRequestTest
  %w[GET HEAD OPTIONS TRACE].each do |method|
    test "#{method} is a safe method" do
      request = stub_request("REQUEST_METHOD" => method)
      assert_predicate request, :safe_method?
      assert_not_predicate request, :unsafe_method?
    end
  end

  %w[POST PUT PATCH DELETE].each do |method|
    test "#{method} is an unsafe method" do
      request = stub_request("REQUEST_METHOD" => method)
      assert_not_predicate request, :safe_method?
      assert_predicate request, :unsafe_method?
    end
  end
end

設計判断

既存の述語メソッドへの委譲という最小限の実装が選ばれました。get?head? といった個別の述語メソッドはすでに ActionDispatch::Request に存在しており、safe_method? はそれらを組み合わせるだけです。新たな HTTP メソッド判定ロジックを持たないため、既存の動作に影響を与えません。

unsafe_method?!safe_method? として実装することで、安全性の定義が safe_method? に一元化されています。将来的に安全なメソッドの定義を変更する場合も、safe_method? の1か所を修正するだけで両メソッドの動作が一貫して更新されます。

また、仕様書の節番号(RFC 9110 §9.2.1)をコメントに明記することで、実装の根拠を追跡可能にしています。これは Rails の標準的なコーディングスタイルへの準拠であるとともに、将来の保守担当者への情報提供でもあります。

まとめ

本 PR は小規模ながら、HTTP 仕様の語彙を Rails のインターフェースに直接反映させた変更です。safe_method? / unsafe_method? を使うことで、各コールサイトに散在していた get? || head? パターンが標準化された一語で置き換えられ、仕様に忠実で読みやすいコードを書きやすくなります。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
4c2f1a54

この記事は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:ファイルパス)とGitHubのPRリンク記法(#番号)が正しく使用されています。

対象読者への適合性 ✓ PASS

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

RFCや述語メソッドといった専門用語を適切に用いており、対象読者であるエンジニアに適した技術レベルで記述されています。

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

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

各セクションが総論→各論の構成で書かれ、各段落の先頭にトピックセンテンスが配置されています。1段落1トピックの原則も守られており、非常に読みやすいです。

Diff内容との照合 ✓ PASS

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

記事内で引用されているメソッド定義とテストコードは、提供されたDiffの内容と完全に一致しており、正確です。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「述語メソッド」「コールサイト」「RFC 9110」など、技術用語が正確かつ適切な文脈で使用されています。

説明の技術的正確性 ✓ PASS

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

safe_method?がどのHTTPメソッドを安全とみなすか、unsafe_method?がその否定であることなど、技術的な説明はすべて正確で論理的です。

事実の突合 ✓ PASS

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

記事内のすべての主張はPRのDescriptionやDiff内のコードで裏付けられており、ハルシネーション(捏造)は見られません。

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

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

PR番号(#57124)やRFCの節番号(9.2.1)などの数値や固有名詞はすべて正確に記載されています。

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

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

記事のタイトルはPRのタイトルと内容を正確に反映しており、主題のズレはありません。

外部知識の正確性 ✓ PASS

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

PRで言及されていない外部知識(バージョンサポート状況、リリース日程など)の追加はなく、PRの情報に忠実です。

時間表現の正確性 ✓ PASS

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

時間表現に関する記述はなく、PRの内容と矛盾する点はありません。