Rails 6在开发中(zeitwerk模式下)未能正确自动加载类

3

我的理解是Rails默认情况下可以自动加载以app文件夹命名的类。

但我遇到了问题,发现无法自动加载,因此想看看您是否能找出代码中明显的问题。

我的文件夹/文件:

app
   blueprints
      concerns
         ingredient_blueprint_concern.rb
      liqueur_blueprint.rb
   controllers
   models
   ...

#app/blueprints/concerns/ingredient_blueprint_concern.rb

module Concerns
  module IngredientBlueprintConcern
    extend ActiveSupport::Concern

    included do
      attributes :name
    end
  end
end


# app/blueprints/liqueur_blueprint.rb

class LiqueurBlueprint < BaseBlueprint
  include ::Concerns::IngredientBlueprintConcern

  # ...
end

rails 控制台:

> Concerns
=> NameError (uninitialized constant Concerns
   Did you mean?  Concurrent):

这似乎与新的 Rails 6 Zeitwerk 模式有关。如果我回到 classic 模式(使用下面的代码),它似乎可以正常工作:

# application.rb
config.autoloader = :classic
2个回答

1

https://github.com/rails/rails/issues/36054

好的,事实证明concerns文件夹实际上在rails加载路径中,这意味着它们不应该命名空间,就像类app/models不在Models命名空间中一样。

它们在Rails 5中工作的事实是某种副作用,我不会在这里详细说明,但您可以在上面的链接中了解更多信息。


1

我想知道我们能否得到一个答案...

# app/foo/bar.rb

module Foo
  class Bar
    def output
      'worked'
    end
  end
end


irb(main):001:0> Foo
NameError (uninitialized constant Foo)

irb(main):002:0> Bar
Zeitwerk::NameError (expected file /Users/simon/Projects/tmp/test_module/app/foo/bar.rb to define constant Bar, but didn't)

irb(main):003:0> Foo
=> Foo

但是

irb(main):007:0> ActiveSupport::Dependencies.autoload_paths.include?("/Users/simon/Projects/tmp/test_module/app/foo")
=> true

如果我先调用Bar再调用Foo,为什么它会起作用?自动加载问题吗?

编辑(2020年8月1日)

将文件路径更改为app/foo/foo/bar.rb使其工作。目前对我来说是一个解决方法。


首先,由于您是新手,请知道您不能将自己的问题作为另一个答案发布。据我所知,你的“问题”并不是问题,这就是Rails一直以来的工作方式。您不需要为位于/app根目录(或任何autoload_paths文件夹中)的文件中定义的类添加命名空间。当您定义模型时,您不会将它们定义在Model命名空间中,对于您的foo文件夹也完全相同。 - Robin
我感到困惑的原因是Rails 6对concerns的处理方式有所改变。以前,如果concerns在models/concerns中,你不必为它们命名空间。现在这些concerns文件夹在自动加载路径中,所以你不需要命名空间。 - Robin

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