Fix ActiveRecord dependency check for Zeitwerk eager loading#504
Fix ActiveRecord dependency check for Zeitwerk eager loading#504trevorturk wants to merge 2 commits intocrmne:mainfrom
Conversation
|
This one is much easier to view with Hide Whitespace enabled: https://github.com/crmne/ruby_llm/pull/504/files?w=1 |
Adds validation that Zeitwerk can eager load all files without errors. This catches autoloading issues like inflector bugs and missing conditional checks before they reach production. - Added check after linter step for fast fail - Runs on all Ruby/Rails matrix combinations - ~2 second check prevents production crashes ## Blocked This PR depends on crmne#504 (ActiveRecord dependency fix) to pass. Without it, the eager loading check fails with NameError. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Adds a validation step that runs Zeitwerk::Loader.eager_load_all after dependency installation to catch autoloading issues early in the CI pipeline. This check helps prevent production crashes by detecting: - Inflector configuration errors - Constant definition issues - Missing conditional checks for optional dependencies The check runs quickly (~2 seconds) before the test matrix, providing rapid feedback on structural issues. Note: This check currently fails due to upstream ruby_llm ActiveRecord dependency issues. See: - crmne/ruby_llm#504 - crmne/ruby_llm#505 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Thanks for the work here. I closed #505 so we can fold it into #504 and keep this as one complete fix.
Could you please update #504 with the following?
- Add the CI eager-load check from #505 into this PR.
- We do want that guard in CI, just bundled with the code changes it depends on.
- Keep the Railtie
ActiveSupport.on_load(:active_record)integration.
- This is the right Rails hook: AR-related code only runs when ActiveRecord is actually loaded.
- Remove the top-level
if defined?(ActiveRecord::Base)wrappers in AR files (acts_as.rb,acts_as_legacy.rb,chat_methods.rb,message_methods.rb,model_methods.rb).
- Those wrappers can make a file load as a no-op if AR isn’t ready yet.
- Later requires won’t re-run the file, so constants/modules may stay undefined.
- Better pattern: define modules normally, and control when they are included via Railtie hooks.
- Add explicit requires for direct dependencies in those files (for example
require "active_support/concern"whereActiveSupport::Concernis used).
- This avoids relying on incidental load order and makes eager loading more reliable.
- Run the eager-load check in appraisal/matrix context (same Rails version under test).
- That makes sure the check validates the actual gem set for each matrix target, not just the base bundle.
Reason for all of this: we keep the Rails eager-loading fix, avoid subtle load-order traps, and keep a clean path for possible non-Rails ActiveRecord support later (CLI/Sinatra).
c024641 to
eadc24d
Compare
|
Apologies for the delay. I made the updates as requested but please let me know if I misunderstood something or if there's anything else to change. Thanks! |
eadc24d to
b808b6d
Compare
| bundle install | ||
| bundle exec appraisal ${{ matrix.rails-version }} bundle install | ||
|
|
||
| - name: Run eager-load guard (appraisal) |
There was a problem hiding this comment.
This is not really needed. you can do it in the test helper
| @@ -1,5 +1,8 @@ | |||
| # frozen_string_literal: true | |||
|
|
|||
| require 'active_support/concern' | |||
There was a problem hiding this comment.
every require should in line 4 of railtie , after if defined?(Rails::Railtie)
Then you dont have dups.
Summary
Zeitwerk::NameErrorwhen eager loading without ActiveRecord presentlib/ruby_llm/active_record/*.rbfiles withif defined?(ActiveRecord::Base)checkactive_recorddirectory to Zeitwerk ignore listDetails
This PR ensures all ActiveRecord integration files only define their modules when ActiveRecord is available, following the pattern for conditional module loading.
Changes:
acts_as.rb,acts_as_legacy.rb,chat_methods.rb,message_methods.rb, andmodel_methods.rbwithif defined?(ActiveRecord::Base)loader.ignore("#{__dir__}/ruby_llm/active_record")to prevent Zeitwerk from auto-loading these conditional fileslib/ruby_llm.rb(now only in railtie)Testing:
🤖 Generated with Claude Code