ActiveAdmin加载过慢:如何禁用i18n-active_record多语言减少数据库查询
这个问题我之前也碰到过!i18n-active_record配合ActiveAdmin确实会因为大量的翻译查询拖慢后台,尤其是当资源字段多的时候。这里有几个可行的解决方案,你可以根据自己的需求选:
方案1:在ActiveAdmin请求中临时切换到YAML翻译后端
这个方法最直接,让ActiveAdmin完全绕过数据库翻译,只用默认的YAML文件里的翻译。你只需要在ActiveAdmin的初始化配置里添加一个around_action,在请求开始时切换到Simple后端,请求结束后恢复原来的后端:
# config/initializers/active_admin.rb ActiveAdmin.setup do |config| # 你的其他ActiveAdmin配置... config.around_action do |controller, block| # 保存原来的I18n后端(也就是i18n-active_record的后端) original_backend = I18n.backend # 切换到默认的Simple后端,加载YAML翻译文件 I18n.backend = I18n::Backend::Simple.new I18n.load_path += Dir[Rails.root.join('config', 'locales', '*.{rb,yml}').to_s] I18n.reload! # 执行当前请求的逻辑 block.call # 请求结束后恢复原来的后端,不影响前台功能 I18n.backend = original_backend end end
这样一来,ActiveAdmin的所有翻译都会从YAML文件读取,不会再触发任何translations表的查询,后台加载速度会立刻提升。
方案2:用链式后端让YAML翻译优先于数据库
如果你不想完全禁用ActiveAdmin的数据库翻译(比如某些自定义标签存在数据库里),可以设置链式后端,让I18n先查YAML文件,找不到的时候再去查数据库。这样既保留了前台的数据库翻译功能,又能让ActiveAdmin用YAML里的默认翻译,减少大部分查询:
# config/initializers/i18n.rb I18n.backend = I18n::Backend::Chain.new( I18n::Backend::Simple.new, # 先查YAML I18n::Backend::ActiveRecord.new # YAML找不到再查数据库 )
这个方案不需要改ActiveAdmin的配置,只需要调整I18n的后端顺序。因为ActiveAdmin的大部分默认翻译(比如模型名称、按钮文本)都已经在YAML文件里了,所以几乎不会触发数据库查询。
方案3:启用I18n缓存
如果上面两个方案都不符合你的需求,还可以启用I18n的缓存功能,把翻译结果缓存起来,这样即使查询数据库,也只会查一次,后续请求从缓存读取:
# config/initializers/i18n.rb I18n.cache_store = ActiveSupport::Cache::RedisCacheStore.new(url: ENV["REDIS_URL"]) # 或者用内存缓存(适合开发环境) # I18n.cache_store = ActiveSupport::Cache::MemoryStore.new
这个方法能显著减少数据库的重复查询,但还是会有第一次的查询,适合那些偶尔需要在ActiveAdmin里用数据库翻译的场景。
我自己当时用的是方案1,后台加载速度从几秒降到了几百毫秒,效果非常明显。你可以根据自己的实际情况选择最合适的方法。
内容的提问来源于stack exchange,提问作者Haseeb Ahmad

