Rails 5:在生产中加载lib文件

时间:2016-07-05 08:30:26

标签: ruby-on-rails autoload ruby-on-rails-5

我已将我的一个应用程序从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,但我想知道是否有更好的解决方案。必须有一个原因,默认情况下在生产中禁用自动加载。

11 个答案:

答案 0 :(得分:131)

转到Rails 5之后的更改列表:

  1. lib目录放入app,因为应用内的所有代码都是自动加载在dev中,急切加载在prod中,最重要的是在开发中自动加载,这样您每次进行更改时都不必重新启动服务器。
  2. 删除require内指向您自己的类的所有lib语句,因为如果它们的文件/目录命名正确,它们都会自动加载,如果您保留require语句,它可能会中断autoreloading。更多信息here
  3. 在所有环境中设置config.eager_load = true,以便在开发中热切地查看代码加载问题。
  4. 在玩线程之前使用Rails.application.eager_load!以避免“循环依赖”错误。
  5. 如果您有任何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(尚未定义),也不依赖于急切加载(对于环境可能已关闭)。