我已将我的一个应用程序从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
,但我想知道是否有更好的解决方案。必须有一个原因,默认情况下在生产中禁用自动加载。
答案 0 :(得分:131)
转到Rails 5之后的更改列表:
lib
目录放入app
,因为应用内的所有代码都是自动加载在dev中,急切加载在prod中,最重要的是在开发中自动加载,这样您每次进行更改时都不必重新启动服务器。require
内指向您自己的类的所有lib
语句,因为如果它们的文件/目录命名正确,它们都会自动加载,如果您保留require
语句,它可能会中断autoreloading。更多信息here config.eager_load = true
,以便在开发中热切地查看代码加载问题。Rails.application.eager_load!
以避免“循环依赖”错误。如果您有任何ruby / rails扩展,请将该代码保留在旧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 }
答案 1 :(得分:52)
我刚刚使用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')
!
答案 2 :(得分:28)
由于线程安全,在生产环境中禁用自动加载。感谢@Зелёный的链接。
我通过将lib
目录中的lib文件存储在我app
目录中的Github建议来解决此问题。 app
文件夹中的每个文件夹都会自动由Rails加载。
答案 3 :(得分:19)
必须有一个原因,在生产中禁用自动加载 默认值。
以下是关于此问题的长篇讨论。 https://github.com/rails/rails/issues/13142
答案 4 :(得分:6)
这允许lib自动重载,也可以在生产环境中工作。
P.S。我已经改变了我的答案,现在它增加了两个急切的自动加载路径,无论环境如何,也允许在自定义环境中工作(如舞台)
# config/initializers/load_lib.rb
...
config.eager_load_paths << Rails.root.join('lib')
config.autoload_paths << Rails.root.join('lib')
...
答案 5 :(得分:3)
只需将config / application.rb文件中的 config.autoload_paths 更改为 config.eager_load_paths 。因为在Rails 5中,默认情况下在生产环境中禁用自动加载。有关更多详细信息,请遵循link。
#config.autoload_paths << "#{Rails.root}/lib"
config.eager_load_paths << Rails.root.join('lib')
它适用于环境开发和生产。
答案 6 :(得分:2)
对于像我这样挣扎于此的人来说,仅仅在app/
下放置一个目录是不够的。是的,您将获得自动加载但不是必需reloading, which requires namespacing conventions to be fulfilled。
此外,使用初始化程序加载旧的根级lib
将阻止在开发过程中重新加载功能。
答案 7 :(得分:2)
从某种意义上说,Rails 5中的统一方法是集中热切和自动加载配置,同时只要配置了预先加载的负载就会添加所需的自动加载路径,否则它将无法正常工作:< / p>
# 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
...
答案 8 :(得分:0)
将lib文件夹移动到app有助于解决问题,我的Twitter api无法在生产中运行。我有“未初始化的常量TwitterApi”,我的Twitter API在我的lib文件夹中。
我的application.rb中有config.autoload_paths += Dir["#{Rails.root}/app/lib"]
,但在移动文件夹之前它没有用。
这就是诀窍
答案 9 :(得分:0)
总结Lev的答案:mv lib app
足以让我的所有lib
代码自动加载/自动重新加载。
(rails 6.0.0beta3,但在rails 5.x上也应该可以正常工作)
答案 10 :(得分:0)
我同意某些依赖项属于 lib
,有些可能属于 app/lib
。
我更喜欢为所有环境加载我选择放入 lib
的所有文件,因此我在需要捆绑包后但在打开 config/application.rb
模块之前立即在 MyApplicationName
中执行此操作.
# load all ruby files in lib
Dir[File.expand_path('../../lib/**/*.rb', __FILE__)].each { |file| require file }
这不依赖于 Rails.root
(尚未定义),也不依赖于急切加载(对于环境可能已关闭)。