protected_environmentsをActiveRecordモジュールに移動

rails/rails

protected_environments の設定が ActiveRecord::Base から ActiveRecord モジュールのトップレベルに移動され、グローバル設定として管理されるようになりました。この変更により、設定の意図がコードに明示され、class_attribute の継承機能が実質的に使われていなかった実装上の矛盾が解消されます。

背景

protected_environments は、本番環境など破壊的な操作を禁止すべき環境を指定する設定です。900bfd9class_attribute として実装され、後に 1a411d4class_attribute を使わない実装に変更されましたが、class_attribute のような継承動作は維持されていました。

しかし、データベースタスク内での実際の利用は常に ActiveRecord::Base.protected_environments を参照しており、継承による個別のサブクラス設定は活用されていませんでした。設定は実質的にグローバルとして扱われていたにもかかわらず、クラス属性として定義されていたことが実装上の矛盾となっていました。

技術的な変更

activerecord/lib/active_record.rbprotected_environments の定義が追加され、モジュールレベルのシングルトンメソッドとして実装されました。

変更後の実装:

singleton_class.attr_reader :protected_environments

def self.protected_environments=(environments)
  @protected_environments = environments.map(&:to_s)
end
self.protected_environments = ["production"]

データベースタスクでの参照先も ActiveRecord.protected_environments に変更されています。

activerecord/lib/active_record/migration.rb:

def protected_environment?
  ActiveRecord.protected_environments.include?(last_stored_environment) if last_stored_environment
end

ActiveRecord::Base の既存のメソッドは非推奨として残され、ActiveRecord モジュールの設定にプロキシする実装になりました。

activerecord/lib/active_record/model_schema.rb:

def protected_environments
  ActiveRecord.deprecator.warn <<~MSG
    ActiveRecord::Base.protected_environments is deprecated in favor of
    ActiveRecord.protected_environments and will be removed in Rails 9.0.
  MSG

  if self == ActiveRecord::Base
    ActiveRecord.protected_environments
  elsif defined?(@protected_environments)
    @protected_environments
  else
    superclass.protected_environments
  end
end

ActiveRecord::Base で呼び出された場合はモジュールレベルの設定を返し、サブクラスで呼び出された場合は従来の継承動作を維持します。セッターも同様に、ActiveRecord::Base への代入はモジュールレベルの設定を変更し、サブクラスへの代入は個別のインスタンス変数を設定します。

設計判断

グローバル設定への移行と後方互換性の両立 が設計の中心です。

設定の実体をモジュールレベルに移動しながら、既存の ActiveRecord::Base.protected_environments によるアクセスを非推奨警告付きで維持しています。Rails 9.0 での削除を予告することで、段階的な移行期間を設けています。

サブクラスでの個別設定は引き続き動作しますが、データベースタスクがグローバル設定のみを参照する以上、サブクラスごとの設定は実質的な意味を持ちません。この判断により、設定の意図と実装が一致し、利用者が設定の影響範囲を正しく理解できるようになります。

まとめ

本PRは、設定の実装場所をその実際の用途に合わせて移動した変更です。class_attribute のような継承動作を持ちながら、グローバル設定としてのみ利用されていた矛盾を解消し、設定の意図をコードに明示しています。既存のAPIは非推奨として維持されており、Rails 9.0 までの移行期間が確保されています。

記事メタデータ

Generated by:
Claude Sonnet 4.5 for DiffDaily

この記事は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のコミットID・PR番号のリンク記法は、ガイドラインに準拠して正しく使用されています。

対象読者への適合性 ✓ PASS

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

「class_attribute」や「シングルトンメソッド」といった用語を前提としており、専門知識を持つエンジニアという対象読者に適した技術レベルで記述されています。

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

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

各セクションが総論から各論へ展開され、各段落がトピックセンテンスで始まるなど、パラグラフ・ライティングの原則が守られており、高い可読性を確保しています。

Diff内容との照合 ✓ PASS

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

記事内で引用されているコードブロックは、提供されたDiffの内容と完全に一致しており、変更点を正確に反映しています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「class_attribute」「シングルトンメソッド」「プロキシ」などの技術用語が、文脈に沿って正確かつ適切に使用されています。

説明の技術的正確性 ✓ PASS

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

設定がグローバルとして扱われていた実装上の矛盾を解消するという変更の目的や、非推奨化による後方互換性の担保といった説明は、技術的に正確で論理的です。

事実の突合 ✓ PASS

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

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

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

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

PR番号(#56749)、コミットID(900bfd9, 1a411d4)、バージョン番号(Rails 9.0)はすべて正確に記載されています。

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

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

記事のタイトル「protected_environmentsをActiveRecordモジュールに移動」は、PRのタイトルと一致しており、内容を的確に表現しています。

外部知識の正確性 ✓ PASS

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

記事内で言及されている「Rails 9.0」というバージョン情報は、Diff内の非推奨警告メッセージに基づいたものであり、PRに記載のない外部知識の捏造ではありません。

時間表現の正確性 ✓ PASS

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

「後に...変更されました」「Rails 9.0での削除を予告」といった時間表現は、PRの文脈と一致しており、事実を正確に伝えています。