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


128

我已将我的应用程序之一从Rails 4.2.6升级到Rails 5.0.0。该升级指南说,是自动加载功能在生产中默认情况下禁用现在。

现在,在生产服务器上总是出现错误,因为我在application.rb文件中加载了所有带有自动加载功能的lib 文件。

module MyApp
    class Application < Rails::Application
        config.autoload_paths += %W( lib/ )
    end
end

现在,我将其设置为config.enable_dependency_loadingtrue但是我想知道是否有更好的解决方案。必须有一个默认情况下在生产中禁用自动加载的原因。


疯狂的事情,而文档仍然告诉您执行auto_load。对于新应用的生产环境中出现的问题,我感到非常困惑。自从我开始学习Rails 5以来,我还没有阅读迁移指南。我提出了一个文档问题,希望能解决这个问题:github.com/rails/rails/issues/27268
akostadinov

1
令人惊讶的是,我在libdir中有两个文件,一个文件在运行时很容易获得,但是另一个必须手动进行:D
illusionist'Jan

@Tobias您最终得到了什么解决方案?
geoboy

@geoboy我将代码(如Validators)直接分组在app /目录中的文件夹中,因为其中的代码是自动加载的。
Tobias '18

这是关于正确的文件路径和类定义的,这是在Rails 5.2中对我有用的:文件路径:app/services/paylinx/paylinx_service.rb类定义:module Paylinx class PaylinxService end end。我尝试了这些autoload_paths东西。对我不起作用。
NamNamNam

Answers:


161

我转向Rails 5后的更改列表:

  1. 地方libDIR到app,因为里面的应用程序的所有代码被自动加载在开发和渴望加载在督促,最重要的是autoreloaded在发展,所以你不必重新启动每次更改时间服务器。
  2. 删除所有require指向您自己的类的语句,lib因为如果它们的文件/目录命名正确,它们都会自动加载,如果您留下这些require语句,则可能会破坏自动重新加载。更多信息在这里
  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 }

8
那么lib现在如何使用该文件夹?我的意思是将libdir移到appdir似乎是一种解决方法。
Martin Svoboda

3
/app/lib/放置了一个文件/类,并且不会自动加载。在Rails 5.1中进行了测试,新项目
Tim Kretschmer

29
值得注意的是,您需要停止弹簧。我将所有内容移至app / lib /,然后浪费了一些时间,想知道为什么我仍然无法从控制台使用我的课程。春天停止ftw :)
jacklin

1
下一行到哪里去?Rails.application.eager_load!
史蒂文·阿吉拉尔

1
这可能有效,但这不是最佳解决方案。文件夹结构也是语义的。在物联网lib有不同的感觉亲近的项目比在东西app目录。其他几个答案比这个答案更好。
CWitty

84

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

它适用于开发和生产环境。

感谢约翰的建议,以取代#{Rails.root}/libRails.root.join('lib')


3
奇迹般有效。我不喜欢该语法,因此将其更改为config.eager_load_paths << Rails.root.join('lib')
3limin4t0r

2
对我来说,这是最好的答案。我的项目从头开始在Rails 5.2上,并且/ lib文件夹仍然是在/ app文件夹之外创建的。我认为没有充分的理由来移动它。
萨米尔·哈达德

1
是的,这有效!似乎Rails开发人员真的很喜欢引起lib加载问题:D,直到下次!
Damien Roche

config.eager_load_paths += [Rails.root.join('lib')]改为使用Rails 5.2,因为 config.eager_load_paths它是冻结数组
William Wong Garay

当您尝试在初始值设定项中修改@WilliamWongGaray config.eager_load_paths时为只读。当您在application.rb其中添加路径时,可以同时使用这两种方法。
米哈尔扎莱夫斯基

31

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

我按照Github的建议通过将lib文件存储在目录中的lib文件夹中来解决此问题。文件夹中的每个文件夹都会由Rails自动加载。appapp


6
如果您不想在Github上进行冗长的讨论,可以在这里找到简化的解释:collectionidea.com/blog/archives/2016/07/22/…–
Ernest

7
我使用config.eager_load_paths << "#{Rails.root}/lib",最好是IMO遵循推荐的rails应用程序结构。
akostadinov

2
eXa

4
这完全破坏了目的lib。我会等着投标之爱或DHH发出声音。与此同时,我(个人)建议坚持使用@Lev Lukomsky的回答。
乔什·布罗迪

@JoshBrody我现在的观点是,您根本不需要该/lib目录。第三方库大多数时候都是宝石,如果没有,则应该创建一个宝石。对于其他文件,我在/app目录中创建特定的文件夹。例如validators
Tobias


12

这允许具有lib autoreload,并且也可以在生产环境中工作。

PS我改变了答案,现在它增加了两个急切的问题:自动加载路径,无论环境如何,也允许在自定义环境中工作(例如舞台)

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

2
您能否继续说明为什么可以解决此问题?
Stuart.Sklinar,

@ Stuart.Sklinar这允许具有lib autoreload,并且也可以在生产环境中工作。PS我改变了我的答案,现在它增加了两个急切的问题:自动加载路径,无论环境如何,也允许在自定义环境中工作(如舞台)
srghma

1
您能否扩大(回答)?仅代码回答并不能真正帮助任何人理解为什么要“那样”完成-我应该补充一点,我不是Ruby开发人员,只是帮助清除SO。在“仅代码答案”中添加一些注释将为其提供一些实际的上下文。
Stuart.Sklinar,

1
@ Stuart.Sklinar当然
srghma

6

只需在config / application.rb文件中将config.autoload_paths更改为config.eager_load_paths。因为在Rails 5中,默认情况下在生产环境中禁用了自动加载。有关更多详细信息,请单击链接

 #config.autoload_paths << "#{Rails.root}/lib"
  config.eager_load_paths << Rails.root.join('lib')

它适用于环境开发和生产。


4

从某种意义上说,这是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文件夹移至应用程序有助于解决问题,我的Twitter api无法在生产环境中运行。我有“未初始化的常量TwitterApi”,并且我的Twitter API在我的lib文件夹中。我config.autoload_paths += Dir["#{Rails.root}/app/lib"]在application.rb中,但是在移动文件夹之前它不起作用。

这成功了


-6

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.