我们总是习惯将应用程序配置放入环境文件中.这对生产管理没有好处,所以现在我们通过初始化程序加载它:
# myinitializer.rb ApplicationConfig = YAML.load_file("#{Rails.root}/config/application/default.yml").symbolize_keys()
一旦我们开始通过ApplicationConfig访问配置,应用程序测试性能就会变差.一个rspec套件从4秒减少到30秒.
在我们的应用程序控制器中,我们需要使用before_filter执行一些操作,其工作方式如下:
before_filter :extra_control def extra_control if ApplicationConfig.some_flag ... end end
声明指向ApplicationConfig的变量可以完全恢复性能:
config = ApplicationConfig def extra_control if config.some_flag ... end end
为什么?为什么通过全局变量访问它会破坏性能?我们在视图和其他控制器的整个代码库中执行此操作.我们需要以不同的方式做到这一点,例如通过将实例变量注入所有控制器?
编辑:我们确实验证了从YAML加载配置的代码无论哪种方式都被调用一次,因此重复加载似乎不是根本原因.
编辑:事实证明这是一个由设置变量引起的错误,该变量被加载为字符串而不是布尔值,导致应用程序进入测试睡眠模式:(对不起,感谢您的尝试.我生命的3天我永远不会回来!
解决方法
我不能说你为什么你的方法很慢,但可能有一种不同的处理设置方式值得研究.我更喜欢有一个包含配置信息的单例类的想法:
class SiteSettings def initialize @settings = {} end @@instance = SiteSettings.new def set_setting(key,value) @settings ||= {} @settings[key] = value end def self.setting(key,value) @@instance.set_setting(key,value) end def settings @settings end def self.method_missing(meth,*args,&block) if @@instance.settings.has_key?(meth) @@instance.settings[meth] else super end end setting :test_setting,'test' setting :another_test_setting '.....' end puts SiteSettings.test_setting puts SiteSettings.another_test_setting
Discourse app采用了类似的方法.