在我们的app
目录中,我们希望某些子目录包含命名空间类,而某些子目录包含顶级类。例如:
app/models/user.rb
定义::User
app/operations/foo.rb
定义::Operations::Foo
app/operations/user/foo.rb
定义::Operations::User::Foo
我们的application.rb
包含以下配置:
config.paths = Rails::Paths::Root.new(Rails.root)
config.paths.add 'app/models', eager_load: true
config.paths.add 'app', eager_load: true
这在大多数情况下都可以正常工作,但有时候在开发模式下使用Rails'自动加载打开,这导致加载错误的类。例如,::User
被误认为是Operations::User
,反之亦然。
有没有办法配置此行为,以便它可以正常工作?
如果没有,我能想到的唯一解决方法是为" namespaced"创建第二个目录。类,与app
和app_namespaced
一致。或者app/namespaced
,因为应用级代码应位于app
内。但这对我来说似乎是丑陋的变通方法。
编辑:@dgilperez所要求的一个小例子:
# app/models/user.rb
class User
end
# app/models/group.rb
class Group
def some_method
# Since we're in a top-level namespace, User should always
# resolve to ::User. But, depending on some seemingly random
# factors, it sometimes resolves to Operations::User.
User.new
end
end
# app/operations.rb
module Operations
end
# app/operations/user/create.rb
module Operations::User
class Create
def some_method
# Here, as expected, I need to prefix with "::" as
# 'User' would refer to the module we're currently in.
# That's fine and works.
::User.new
end
end
end
答案 0 :(得分:0)
是的,这是rails自动加载的缺点。默认情况下,它会加载/app
中的所有内容,但第一级目录结构不是名称的一部分。这样app/models/user.rb
可以定义User
,而不是Models::User
。
您无需弄乱加载路径。这里提供了几种方法/解决方法。
在我当前的项目中,我们只需将命名空间目录加倍。这意味着如果我们要定义ServiceObjects::User::Import
,我们会将其放入app/service_objects/service_objects/user/import.rb
我个人更喜欢这种方法的变体,即将所有“非标准”内容放入app/lib
(可以是app/custom
或任何你想要的东西)。通过这种方式,目录名称没有奇怪的重复,所有自定义代码都包含在内。