我已将我的一个应用程序从Rails 4.2.6升级到Rails 5.0.0。 Upgrade Guide说,自动加载功能现在默认在生产中被禁用。
现在我总是在生产服务器上出现错误,因为我在application.rb
文件中加载了自动加载的所有lib文件。
module MyApp
class Application < Rails::Application
config.autoload_paths += %W( lib/ )
end
end
现在,我已经将config.enable_dependency_loading
设置为true
,但我想知道是否有更好的解决方案。必须有一个原因,默认情况下在生产中禁用自动加载。
移动到Rails 5后的更改列表:
lib
目录放入app
,因为应用程序内的所有代码都在dev中自动加载并且在prod中加载,最重要的是在开发中自动加载,因此每次进行更改时都不必重新启动服务器。require
中指向您自己的类的所有lib
语句,因为如果它们的文件/目录命名正确,它们都是自动加载的,并且如果您保留require
语句,它可能会破坏自动加载。更多信息hereconfig.eager_load = true
以在dev中热切地查看代码加载问题。Rails.application.eager_load!
以避免“循环依赖”错误。lib
目录中,并从初始化程序手动加载它们。这将确保在您可以依赖它的其他逻辑之前加载扩展:
# config/initializers/extensions.rb
Dir["#{Rails.root}/lib/ruby_ext/*.rb"].each { |file| require file }
Dir["#{Rails.root}/lib/rails_ext/*.rb"].each { |file| require file }
我只是使用config.eager_load_paths
而不是config.autoload_paths
就像在github评论中提到akostadinov:https://github.com/rails/rails/issues/13142#issuecomment-275492070
# config.autoload_paths << Rails.root.join('lib')
config.eager_load_paths << Rails.root.join('lib')
它适用于开发和生产环境。
感谢Johan建议用#{Rails.root}/lib
取代Rails.root.join('lib')
!
由于线程安全,在生产环境中禁用自动加载。感谢@Зелёный的链接。
我通过在lib
上推荐的app
目录中的Github文件夹中存储lib文件来解决这个问题。 app
文件夹中的每个文件夹都会自动由Rails加载。
必须有一个原因,默认情况下在生产中禁用自动加载。
这是一个关于这个问题的长期讨论。 https://github.com/rails/rails/issues/13142
这允许lib自动重载,也可以在生产环境中工作。
附:我已经改变了我的答案,现在它增加了两个渴望 - 自动加载路径,无论环境如何,也允许在自定义环境中工作(如阶段)
# config/initializers/load_lib.rb
...
config.eager_load_paths << Rails.root.join('lib')
config.autoload_paths << Rails.root.join('lib')
...
对于像我这样苦苦挣扎的人来说,仅仅在app/
下放置一个目录是不够的。是的,你会得到自动加载,但不是必要的reloading, which requires namespacing conventions to be fulfilled。
此外,使用初始化程序加载旧的根级别lib
将阻止在开发过程中重新加载功能。
从某种意义上说,这里是Rails 5中统一的方法来集中热切和自动加载配置,同时每当配置了预先加载的负载时它都会添加所需的自动加载路径,否则它将无法正常工作:
# config/application.rb
...
config.paths.add Rails.root.join('lib').to_s, eager_load: true
# as an example of autoload only config
config.paths.add Rails.root.join('domainpack').to_s, autoload: true
...
将lib文件夹移动到app有助于解决问题,我的Twitter api不会在生产中运行。我有“未初始化的常量TwitterApi”,我的Twitter API在我的lib文件夹中。我在我的application.rb中有config.autoload_paths += Dir["#{Rails.root}/app/lib"]
,但在移动文件夹之前它没有用。
这样做了
总结列夫的答案:mv lib app
足以让我所有的lib
代码自动加载/自动重新加载。
(rails 6.0.0beta3但也应该在rails 5.x上正常工作)