| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
The engine required app/models/solid_objects/record.rb at the top of the file, so `require "solid_objects"` defined a subclass of ActiveRecord::Base. Bundler.require runs that before the host application boots, which loaded ActiveRecord::Base during railtie setup instead of on first use. That moved every deferred on_load(:active_record) hook in the host application forward. The Active Record railtie registers its encryption configuration inside on_load(:active_record_encryption), and the constant was already loaded, so the hook ran at once, before config/initializers. An application that assigns its encryption keys in an initializer got Encryption.configure with nils, and every encrypted attribute then raised a missing credential error far from the cause. The engine now requires the record class from an on_load(:active_record) hook, so nothing touches ActiveRecord::Base until the application does. The record class also configures its own connection now. The initializer could no longer call configure_connection: Zeitwerk can load record.rb first, and the superclass expression there is what loads ActiveRecord::Base, so the hook would run while SolidObjects::Record was still undefined. Reading the configuration in the class body also survives a development reload, which the initializer did not. Fixes #38
Greptile SummaryThe PR defers loading SolidObjects::Record until Active Record loads, preserving host initializer timing while moving connection setup into the record class so it is reapplied when that class loads.
Confidence Score: 5/5The PR appears safe to merge with no actionable correctness, security, or repository-rule violations identified. The new hook preserves Active Record’s deferred initialization, the class-body connection setup handles both hook-driven and autoload-driven class definition, and the packaged gem retains the required model path. Important Files Changed
Sequence DiagramsequenceDiagram
participant Host as Host application
participant Engine as SolidObjects::Engine
participant Init as config/initializers
participant AR as Active Record
participant Record as SolidObjects::Record
Host->>Engine: Load Solid Objects engine
Engine->>AR: Register on_load(:active_record)
Host->>Init: Run application initializers
Init->>Host: Set encryption keys and connects_to
Host->>AR: Load ActiveRecord::Base
AR->>Engine: Run active_record load hook
Engine->>Record: Require record.rb
Record->>Record: configure_connection
Reviews (1): Last reviewed commit: "Load the record class when Active Record..." | Re-trigger Greptile |
Sorry, something went wrong.
Bumps the version constant, dates the changelog section for the deferred Active Record load, and refreshes the lockfile.
| Back | FazBrowse Home | New Git URL |
Fixes #38.
Cause
lib/solid_objects/engine.rb required app/models/solid_objects/record.rb at
the top of the file, and SolidObjects::Record is a subclass of
ActiveRecord::Base. Bundler.require runs that before the host application
boots, so ActiveRecord::Base loaded during railtie setup instead of on first
use.
That moved every deferred on_load(:active_record) hook in the host
application forward. The Active Record railtie registers its encryption
configuration inside on_load(:active_record_encryption). The constant was
already loaded, so that hook ran at once, before config/initializers. An
application that assigns its encryption keys in an initializer got
Encryption.configure with nils, and the later assignment was discarded.
Change
hook, so nothing touches ActiveRecord::Base until the application does.
The initializer could no longer call configure_connection: Zeitwerk can
load record.rb first, and the superclass expression there is what loads
ActiveRecord::Base, so the hook would run while SolidObjects::Record was
still undefined. Reading the configuration in the class body also survives a
development reload, which the initializer did not.
Tests
test/integration/active_record_load_timing_test.rb is new. One test asks a
fresh process whether require "solid_objects" leaves the :active_record
load hooks deferred. The other boots the dummy application, which now assigns
encryption keys in config/initializers, and reads the key back.
test/integration/engine_test.rb gains a test that boots the dummy
application with connects_to configured in an initializer and asserts the
record class owns its own connection pool. That test passes on main, so it
records the behaviour the class-body change had to keep.
Observed failures before the fix:
With the engine fix in place but configure_connection removed from the record
class body:
Validation
bundle exec rake (tests, Standard Ruby, RuboCop, RBS, Steep, Brakeman):
535 runs, 1768 assertions, 0 failures, 0 errors, 15 skips. The skip count
matches main.