我可以强制Rails自动加载的命名空间而不嵌套在文件夹中吗?

时间:2015-03-11 11:11:40

标签: ruby-on-rails ruby ruby-on-rails-4

有没有办法告诉Rails某个文件夹中的所有文件都包含在某个名称空间中?

我在bar.rb中有一个文件app/foo。 Rails会假定此文件定义Bar,但我希望此文件定义Foo::Bar

我知道我可以通过将我的root添加到Rails的自动加载路径来实现这一点,但这不是一个真正的解决方案。有没有其他方法可以告诉Rails app/foo中的所有文件都位于Foo命名空间中?

编辑:文件树以便澄清

app
  assets
  controllers
  models
  foo
    bar.rb
    quux.rb

我希望能够分别在Foo::BarFoo::Quux中定义bar.rbquux.rb,同时还可以使用Rails自动加载。无需采用如下的树结构:

app
  assets
  controllers
  models
  foo
    foo
      bar.rb
      quux.rb

3 个答案:

答案 0 :(得分:3)

您可以通过在应用程序配置中的自动加载路径中添加/app来自动加载名称空间与/app中目录相对应的文件。

# config/application.rb
config.autoload_paths << "#{config.root}/app"

我不确定这是否是问题的作者

  

我知道我可以通过将根目录添加到Rails的自动加载路径中来实现此目的,但这不是一个真正的解决方案。

但这绝对是一个真实的解决方案,也是正确的解决方案。这样做很好,而且根据我的经验,这一点也不罕见。

只有很小的副作用,那就是采用您想要的不一致的命名约定的代价。如果您引用的未定义常量与应用程序中另一个目录的名称匹配,则会收到稍有不同的错误消息。

# Models::Foo => LoadError (Unable to autoload constant Models::Foo, expected /app/models/foo.rb to define it)

但是,如果您已有与app中的目录匹配的名称空间,则加载仍然可以正常进行。这是Rails的工作:

它将采用添加到config.autoload_paths的路径并将其添加到默认路径(app下的目录:app/modelsapp/controllersapp/foo等)。然后,当引用尚未加载的常量时,Rails会沿着这些路径前进,寻找与常量匹配的路径。因此,当您引用Foo::Bar时,它将查找app/models/foo/bar.rbapp/controllers/foo/bar.rb等,直到找到定义了Foo::Bar的文件。我们要做的就是在该查询中添加app/foo/bar.rb

答案 1 :(得分:0)

您可以尝试添加Rail的自动加载路径配置中的文件夹

# config/application.rb
# Rails 4
config.autoload_paths << Rails.root.join("app", "foo")

# Rails 5+
 config.eager_load_paths << Rails.root.join("app", "foo")

答案 2 :(得分:-1)

Rails不假设命名空间,它假设源文件的路径取决于命名空间,因此:

$ cat app/foo/bar.rb 
module Foo
  class Bar
    def bar
      puts "i'm here"
    end
  end
end

$ rails c
2.2.0 :007 > b=Foo::Bar.new
 => #<Foo::Bar:0x00000005272770> 
2.2.0 :008 > b.bar
i'm here
 => nil