如何在Rails的开发模式下自动为每个请求重新加载gem代码?

我正在开发一个Rails应用程序,其中大部分不是特定于应用程序的代码都是在各种gem中编写的,包括一些Rails引擎和一些我正在增强或修复bug的第三方gem。

gem 'mygem', path: File.expath_path('../../mygem', __FILE__) 

由于这些gem中的很多代码实际上都是应用程序的一部分,因此它仍然经常变化。 我希望能够利用Railsfunction,在开发时(即config.cache_classes为false时)在每个请求上重新加载代码,但这只在默认情况下在普通应用程序结构中完成。

如何配置Rails以在每个请求上重新加载gem代码,就像使用应用程序代码一样?

ActiveSupport的帮助下,我通过反复试验发现需要执行几个步骤。

  • activesupport添加为.gemspec文件中的依赖.gemspec

     spec.add_dependency 'activesupport' 
  • 在gem的顶级模块中包含ActiveSupport :: Dependencies(这是最难以捉摸的要求)

     require 'bundler'; Bundler.setup require 'active_support/dependencies' module MyGem unloadable include ActiveSupport::Dependencies end require 'my_gem/version.rb' # etc... 
  • 设置您的gem以使用自动加载。 您可以手动使用ruby 自动加载声明将符号映射到文件名,也可以使用Rails样式的文件夹结构到模块层次结构规则(请参阅ActiveSupport #constantize )

  • 在gem中的每个模块和类中,添加unloadable

     module MyModule unloadable end 
  • 在每个依赖于gem中的模块或类的文件中,包括在gem本身中,使用require_dependency在每个文件的顶部声明它们。 根据需要查找gem的路径以正确解析路径。

     require_dependency "#{Gem.loaded_specs['my_gem'].full_gem_path}/lib/my_gem/myclass" 

如果在修改文件和发出请求后出现exception,请检查您是否没有错过依赖项。

有关一些有趣的细节,请参阅有关Rails(和ruby)自动加载的这篇综合文章。