有没有办法告诉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::Bar
和Foo::Quux
中定义bar.rb
和quux.rb
,同时还可以使用Rails自动加载。无需采用如下的树结构:
app
assets
controllers
models
foo
foo
bar.rb
quux.rb
答案 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/models
,app/controllers
,app/foo
等)。然后,当引用尚未加载的常量时,Rails会沿着这些路径前进,寻找与常量匹配的路径。因此,当您引用Foo::Bar
时,它将查找app/models/foo/bar.rb
,app/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