为什么Rails不能自动加载app/services中的类?

72
我正在开发一个Rails 4.2应用程序,并刚刚将app/services/fetch_artists.rb添加到结构中。在这个文件里,我定义了一个class FetchArtists; end
当尝试运行rails r 'FetchArtists'时,它会给出一个NameError: uninitialized constant FetchArtists错误。
我尝试查看ActiveSupport::Dependencies.autoload_paths,确实,app/services不在其中:
/.../app/assets
/.../app/controllers
/.../app/helpers
/.../app/jobs
/.../app/mailers
/.../app/models
/.../app/controllers/concerns
/.../app/models/concerns
/.../spec/mailers/previews

我的问题是,为什么这个文件夹没有自动加载,我应该怎么做才能让它自动加载?

编辑

非常奇怪,在多次使用rails runner命令后,新的文件夹出现在自动加载路径上。我不知道为什么会有这样的滞后。

有人建议这可能与spring有关。我想听更多关于此的信息,因为这可能对处于同样情况的其他人有所帮助。


也许这个答案可以帮到你。 https://stackoverflow.com/a/44976513/7672657 - napster235
5个回答

125

我遇到了同样的问题,这似乎是Spring的缓存问题。Spring是一个处理应用程序预加载的过程,它被用于Web服务器、控制台和Rake任务。

通过运行bin/spring stop停止Spring将强制Spring重新加载您的应用程序。现在运行rails console并检查ActiveSupport::Dependencies.autoload_paths将成功显示app/services


4
命名很重要,参见此链接 >> https://dev59.com/vJffa4cB1Zd3GeqP95SW - user3738936
1
我想知道这个春季问题是否会在生产中发生。特别是在Heroku,我不知道我们是否可以重启Spring。 - Zia Ul Rehman Mughal
很可能不会,因为您已经添加、提交和部署了新文件。Spring将不会在为您最新部署所启动的Heroku实例上运行。 - germs12

28

在我的情况下,Spring没有观察app/services目录的更改 - 重新启动Spring会加载该类,但对现有类或新类的更改需要重新启动Spring才能应用它们。

为解决此问题,我将其添加到Spring观察的目录列表中,在config/spring.rb中:

%w(
  .ruby-version
  .rbenv-vars
  tmp/restart.txt
  tmp/caching-dev.txt
  app/services
).each { |path| Spring.watch(path) }

再次重启Spring。


14

我遇到了类似的问题,快速浏览了Spring文档,并找到了关于监视器的部分。

我将以下内容添加到我的application.rb中,一切都顺利解决 -

Spring.watch "app/services/**"

我在这方面不是专家,可能会因人而异。


14

我遇到了同样的问题,但没有找到解决方案。我没有耐心等待自动加载最终加载它,所以我的快速解决方案是打开eager_load,并启动服务器。它最终会加载它。之后我关闭了它,我的类仍然被加载。

只需在config/environments/development.rb中使用:config.eager_load = true


-4

你应该将它包含在autoload_paths中:

config.autoload_paths += %W(#{Rails.root}/app/services)

11
据我理解,app 下面的所有内容都会自动加载:http://edgeguides.rubyonrails.org/autoloading_and_reloading_constants.html#autoload-paths - linkyndy
@AndreiHorak 我也注意到了这个问题。你是使用标准的Rails(而不是Rails-api)吗? - dimakura
@AndreiHorak 我的印象是,你必须重新启动服务器才能将新的DIR添加到加载路径中... - Joel
4
他实际上是从命令行尝试的。所以这可能与Spring有关。 - dimakura
是的,我尝试过从rails runnerrails console两方面来解决。所以你可能是对的,这可能与Spring有关。与此相关的回答对其他人也可能有用,所以我很好奇Spring在其中扮演了什么角色。 - linkyndy
3
使用 bin/spring stop 命令停止 Spring 进程,这对我非常有效,允许在下次启动应用程序时自动检测到 app/services 目录。您可以通过检查 ActiveSupport::Dependencies.autoload_paths 在 Rails 控制台中确认自动加载路径。 - bfalling

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接