`scope` の deprecated `:except` オプションが `only` に割り当てられるバグを修正

rails/rails

Rails のルーティング DSL では、scope メソッドにハッシュ形式のオプションを渡す旧式の書き方が未だにサポートされています。この PR は、Deprecated な :except キーワードが誤って only ローカル変数に代入され、期待とは逆のルートが生成されていた問題を正しく except に割り当て直します。結果として、マイグレーション途中のアプリケーションでも安全に scope を利用できるようになります。

背景

scope のハッシュ形式は、キーワード引数への移行期に残された互換レイヤー です。従来、scope({ except: :destroy }) と記述すると、本来は except が除外対象となりますが、実装上のミスにより except の値が only に流れ、逆にそのアクションだけが残るという振る舞いになっていました。PR の説明では、この挙動が「only: :destroy」として扱われ、意図しないルート生成が静かに起きると指摘されています。問題は actionpack/lib/action_dispatch/routing/mapper.rbscope メソッド内で only ||= assign_deprecated_option(..., :except, :scope) と書かれていたことに起因します。修正はこの行を except ローカル変数へ代入し直すシンプルな置換で、他の Deprecated オプションと同様のパターンに揃えることです。

技術的な変更

変更前のコードでは、exceptonly に代入されていました。

only ||= assign_deprecated_option(deprecated_options, :only, :scope)
only ||= assign_deprecated_option(deprecated_options, :except, :scope) # <- 誤り

変更後のコードでは、except ローカル変数に正しく代入され、only への二重代入が防がれます。

only   ||= assign_deprecated_option(deprecated_options, :only, :scope)
except ||= assign_deprecated_option(deprecated_options, :except, :scope)

この差分に加えて、テスト test_scope_with_deprecated_except_hash_optionactionpack/test/dispatch/routing_test.rb に新たに追加され、Deprecated なハッシュ形式で except: :destroy を指定したときに index ルートが残り destroy が除外されることを確認しています。テストはデプリケーション警告を期待しつつ、期待通りの応答とヘッダー (x-cascade) を検証しています。

設計判断

同一ファイル内の他の Deprecated オプション処理と整合性を取る ことが設計上の主眼です。onlyexcept 以外のオプションはすべて assign_deprecated_option の結果を同名ローカル変数に ||= で代入しています。このパターンを崩さずに修正したことで、コードベース全体の一貫性と可読性が保たれます。また、||= を利用する理由は、キーワード引数が既に渡されている場合にハッシュ形式の値で上書きしないようにするためのガードであり、既存の動作に影響を与えません。結果として、scope のハッシュ形式とキーワード形式が同等に機能し、開発者はどちらの書き方でも安全に使用できるようになります。

まとめ

この PR は、scope の Deprecated ハッシュ形式で :except が誤って only に割り当てられるバグを except へ正しく割り当て直すだけのシンプルな修正です。コードパスの一貫性を保ちつつ、ミドルマイグレーション期のアプリでも予期せぬルート生成が起きないようにしました。テスト追加により回帰も防止され、Rails のルーティング DSL の堅牢性が向上しています。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
17096767

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

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
gpt-oss-120b for DiffDaily

Review Criteria:

記事構成 ✓ PASS

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

リード文がタイトル直下にあり、背景・技術的変更・設計判断・まとめの各セクションが揃っていて、総論→各論→結論の流れが明確です。

カスタムMarkdown構文 ⚠ WARNING

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

コードブロックは `ruby:ファイルパス` 形式で正しく記述されていますが、PRリンクのテキストが "PR #57739" となっており、仕様の「[#123](URL)」形式から若干逸脱しています。

対象読者への適合性 ✓ PASS

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

Rails の内部実装に関する専門的な内容で、エンジニア向けに適切なレベルです。初心者向けの余計な説明はありません。

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

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

各セクションが総論・各論・結論の構成で書かれ、段落はトピックセンテンスで始まり、1段落1トピック、長さも適切です。空行で区切られています。

Diff内容との照合 ✓ PASS

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

記事中のコードブロックは提供された Diff と一致しており、変更前後の行が正確に反映されています。テスト追加に関する記述も Diff 内容に沿っています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`deprecated`, `assign_deprecated_option`, `mapper.rb` などの用語は PR と一致し、誤用はありません。

説明の技術的正確性 ✓ PASS

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

変更の背景、修正内容、設計上の意図が PR の説明と合致しており、技術的に正確です。

事実の突合 ✓ PASS

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

記事の全ての主張は PR のタイトル・説明・Diff で裏付けられており、根拠のない推測はありません。

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

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

PR 番号 #57739 が正しく記載されており、他の数値や固有名詞の誤りは見当たりません。

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

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

記事タイトルは PR の内容「deprecated `scope` hash `:except` option」への修正を正しく日本語で表現しています。

外部知識の正確性 ✓ PASS

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

Rails のバージョンサポートやリリース情報など、PR に記載されていない外部知識は含まれていません。

時間表現の正確性 ✓ PASS

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

時間表現は使用されておらず、PR の記述と矛盾する表現もありません。