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

问题描述 投票:99回答:9

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

ruby-on-rails autoload ruby-on-rails-5
9个回答
137
投票

移动到Rails 5后的更改列表:

  1. lib目录放入app,因为应用程序内的所有代码都在dev中自动加载并且在prod中加载,最重要的是在开发中自动加载,因此每次进行更改时都不必重新启动服务器。
  2. 删除require中指向您自己的类的所有lib语句,因为如果它们的文件/目录命名正确,它们都是自动加载的,并且如果您保留require语句,它可能会破坏自动加载。更多信息here
  3. 在所有环境中设置config.eager_load = true以在dev中热切地查看代码加载问题。
  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 }

58
投票

我只是使用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')


29
投票

由于线程安全,在生产环境中禁用自动加载。感谢@Зелёный的链接。

我通过在lib上推荐的app目录中的Github文件夹中存储lib文件来解决这个问题。 app文件夹中的每个文件夹都会自动由Rails加载。


19
投票

必须有一个原因,默认情况下在生产中禁用自动加载。

这是一个关于这个问题的长期讨论。 https://github.com/rails/rails/issues/13142


7
投票

这允许lib自动重载,也可以在生产环境中工作。

附:我已经改变了我的答案,现在它增加了两个渴望 - 自动加载路径,无论环境如何,也允许在自定义环境中工作(如阶段)

# config/initializers/load_lib.rb
...
config.eager_load_paths << Rails.root.join('lib')
config.autoload_paths << Rails.root.join('lib')
...

2
投票

对于像我这样苦苦挣扎的人来说,仅仅在app/下放置一个目录是不够的。是的,你会得到自动加载,但不是必要的reloading, which requires namespacing conventions to be fulfilled

此外,使用初始化程序加载旧的根级别lib将阻止在开发过程中重新加载功能。


2
投票

从某种意义上说,这里是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
...

0
投票

将lib文件夹移动到app有助于解决问题,我的Twitter api不会在生产中运行。我有“未初始化的常量TwitterApi”,我的Twitter API在我的lib文件夹中。我在我的application.rb中有config.autoload_paths += Dir["#{Rails.root}/app/lib"],但在移动文件夹之前它没有用。

这样做了


-2
投票

总结列夫的答案:mv lib app足以让我所有的lib代码自动加载/自动重新加载。

(rails 6.0.0beta3但也应该在rails 5.x上正常工作)

© www.soinside.com 2019 - 2024. All rights reserved.