Rails 6如何在初始化器中实现配置懒加载 解决money-rails多租户适配问题
问题根因
该报错核心源于Rails初始化器的执行顺序:money.rb初始化器加载时,Rails尚未完成Active Storage组件的加载(has_one_attached方法还未注入到ActiveRecord::Base中),同时Tenant模型也未完成加载。在初始化器的lambda中直接引用Tenant常量会触发Rails常量自动加载逻辑,提前加载Tenant模型,进而触发方法不存在的报错。
最优解决方案
按优先级推荐以下方案:
方案1:延迟常量加载,避免初始化阶段预加载Tenant模型
修改money.rb初始化器配置,将Tenant常量的查找延迟到lambda实际执行时触发,不会在初始化器解析阶段就加载模型,侵入性最低,完全适配懒加载设计:
# config/initializers/money.rb MoneyRails.configure do |config| # 延迟查找Tenant常量,仅lambda实际执行时才会加载模型 config.default_currency = -> { ActiveSupport::Dependencies.constantize("Tenant").current.default_currency } end
方案2:通过after_initialize回调保证加载顺序
如果方案1仍存在兼容问题,可以将配置放到Rails的after_initialize回调中,确保所有框架组件、模型都加载完成后再执行配置:
# config/initializers/money.rb Rails.application.config.after_initialize do MoneyRails.configure do |config| config.default_currency = -> { Tenant.current.default_currency } end end
兜底备选方案:请求级别动态设置货币
如果你的多租户切换是按请求维度实现,可以放弃全局配置,在应用控制器中通过around_action动态设置当前请求的货币,逻辑更可控,完全规避初始化阶段的加载问题:
# app/controllers/application_controller.rb class ApplicationController < ActionController::Base around_action :set_current_currency private def set_current_currency previous_currency = Money.default_currency Money.default_currency = Tenant.current.default_currency if Tenant.current yield ensure Money.default_currency = previous_currency end end
内容的提问来源于stack exchange,提问作者Gustavo Borges
相关产品推荐
相关产品推荐

