Arel を単体で require 可能にする変更

rails/rails

Arel を require "arel" しただけでは NameError が発生していましたが、active_support/ractors を先行ロードすることで単体でも正しく利用できるようになりました。

背景

Arel 単体での require が失敗する のは、Arel::Visitors::ToSqlArel::Visitors::PostgreSQL がクラス定義時に ActiveSupport::Ractors を参照しているためです。実際に ruby -I activerecord/lib -e 'require "arel"' を実行すると、uninitialized constant Arel::Visitors::ToSql::ActiveSupport (NameError) がスローされます。この定数は Active Support の autoload に依存しているため、Active Record 経由で Arel がロードされる場合は問題になりませんが、Arel 単体でロードすると解決できませんでした。rails#57840 で報告された通り、arsi など SQL を直接検査するライブラリは Arel の単体ロードを前提としているため、上記の例外が実務に支障をきたしていました。

技術的な変更

activerecord/lib/arel.rb の先頭に require "active_support/ractors" を追加しました。これにより、Arel のロード時に必要な Ractors 関連定数が事前に定義され、NameError が回避されます。

@@ -1,5 +1,7 @@
 # frozen_string_literal: true

+require "active_support/ractors"
+
 require "arel/errors"

 require "arel/crud"

変更は 2 行の追加のみで、既存のロジックには影響を与えていません。また、回帰テストとして activerecord/test/cases/arel/require_test.rb を新規追加し、Active Support を事前にロードせずに require "arel" が成功することを検証しています。

# frozen_string_literal: true

require_relative "helper"

module Arel
  class RequireTest < Arel::Test
    def test_arel_can_be_required_on_its_own
      arel_load_path = $LOAD_PATH.find { |path| File.exist?(File.join(path, "arel.rb")) }
      active_support_load_path = $LOAD_PATH.find { |path| File.exist?(File.join(path, "active_support/ractors.rb")) }

      output = IO.popen(
        [Gem.ruby, "-I", arel_load_path, "-I", active_support_load_path, "-e", 'require "arel"'],
        err: [:child, :out],
        &:read
      )

      assert_predicate $?, :success?, "Expected `require \"arel\"` to succeed on its own, but got:\n#{output}"
    end
  end
end

テストは新しいロードパスを指定して子プロセスで require "arel" を実行し、終了ステータスが成功であることを確認します。変更前はこのテストが失敗し、変更後は確実に成功することが確認されています。

設計判断

ActiveSupport の Ractors 機能を直接ロードする 方針が採用されました。Arel のクラス定義時に必要になる定数を確実に提供するため、条件分岐や遅延ロードを導入せずにシンプルに require "active_support/ractors" を追加しています。このアプローチは実装コストが最小であり、既存の Arel 使用者への互換性を保ちつつ、単体ロードの信頼性を向上させます。

唯一のトレードオフは Arel が ActiveSupport に依存する ことが明示的になる点です。Arel を純粋な独立ライブラリとして扱いたいケースでは、追加の依存が導入されますが、Rails エコシステム内での利用が前提であることを考慮すれば許容範囲と判断されています。代替案としては遅延ロードやモジュール分離が考えられましたが、実装の複雑化とテストカバレッジの維持が難しいため採用されませんでした。

まとめ

この PR は require "active_support/ractors" を追加し、Arel を単体で require した際の NameError を根本的に解消しました。新規テストにより回帰が防止され、SQL を直接解析する外部ライブラリでも安全に Arel を利用できるようになりました。

記事メタデータ

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

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

品質レビュー結果

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

Review Criteria:

記事構成 ✓ PASS

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

リード文・背景・技術的変更・設計判断・まとめの5セクションが揃っており、総論→各論→結論の流れが明確です。

カスタムMarkdown構文 ⚠ WARNING

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

コードブロックは正しい `言語:ファイルパス` 形式ですが、PRリンクは `[PR #57911](URL)` となっており、仕様の `[ #123 ](URL)` 形式と異なります。

対象読者への適合性 ✓ PASS

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

Rails エンジニア向けの技術的記述であり、初心者向けの過度な説明はありません。

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

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

各セクションの冒頭がトピックセンテンスで始まり、1段落1テーマ、6文未満で適切に区切られています。

Diff内容との照合 ✓ PASS

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

記事内のコードブロックは提供された Diff と完全に一致し、ファイル名・変更行数も合致しています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

NameError、ActiveSupport::Ractors、Arel::Visitors::ToSql などの用語は PR と一致し、誤用はありません。

説明の技術的正確性 ✓ PASS

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

要件や変更の効果が PR の説明と合致しており、技術的に正確です。

事実の突合 ✓ PASS

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

全ての主張が PR のタイトル・説明・Diff で裏付けられており、推測や捏造はありません。

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

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

数値や固有名詞は PR 番号 #57911 のみで正確です。

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

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

記事タイトルは PR タイトル「Allow Arel to be required on its own」の意味を日本語で正確に表現しています。

外部知識の正確性 ✓ PASS

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

LTS やリリース日程等、PR に記載されていない外部知識は含まれていません。

時間表現の正確性 ✓ PASS

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

時間表現の記述はなく、PR と矛盾する表現もありません。