# Initializer for Saving Request Data with Uninitialized Constant
## Summary
A Rails initializer attempted to subscribe to controller events using `ActiveSupport::Notifications` and create `RequestLog` records. The `RequestLog` constant was unavailable during initialization, causing `NameError: uninitialized constant RequestLog` failures.
## Root Cause
- The `request_logging.rb` initializer executes **before** Rails loads application classes
- `RequestLog` model hadn't been auto-loaded when the initializer ran
- The `ActiveSupport::Notifications.subscribe` block references `RequestLog` during Rails boot process
## Why This Happens in Real Systems
- Initializers run in alphabetical order before application code loads
- Service/Object dependencies aren't available during early boot phase
- Async event subscribers often require runtime contexts unavailable at initialization
- Multi-stage boot processes in frameworks create temporal coupling risks
## Real-World Impact
- Complete failure of request logging functionality
- Flooded error logs from `NameError` exceptions
- Missing observability data for debugging and performance monitoring
- Gradual degradation of log storage volume metrics
- Undetected application issues due to missing instrumentation
## Example Code
Original Problematic Initializer (`config/initializers/request_logging.rb`):
```ruby
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |name, start, finish, id, payload|
begin
RequestLog.create(
tenant_id: @tenant.id, # FATAL: RequestLog constant undefined here
# ... other attributes ...
)
rescue => e
Rails.logger.error "RequestLog create failed: #{e.class}: #{e.message}"
end
end
How Senior Engineers Fix It
1. Defer execution until full initialization:
Rails.application.config.after_initialize do
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |name, start, finish, id, payload|
# Subscription logic here
end
end
2. Use lazy-load hooks:
ActiveSupport.on_load(:active_record) do
ActiveSupport::Notifications.subscribe("process_action.action_controller") do |*args|
# Handler code
end
end
3. Implement fail-safe constant checking:
return unless defined?(RequestLog)
ActiveSupport::Notifications.subscribe(...) { ... }
4. Context-aware initialization patterns:
class RequestLogSubscriber
def self.register
new.subscribe
end
def subscribe
ActiveSupport::Notifications.subscribe(...) { |args| handle_event(args) }
end
private
def handle_event(payload)
RequestLog.create(...) # Safe: called at runtime
end
end
Rails.application.config.after_initialize { RequestLogSubscriber.register }
Why Juniors Miss It
- Misunderstanding of Rails’ initialization sequence
- Assuming all constants are available in initializers
- Lack of awareness about load order dependencies
- Testing in development where class reloading masks the issue
- Over-reliance on “it works on my machine” without production-like checks
- Not considering Zealous Loading differences between environments