在一个测试应用程序(Rails 7.0,Ruby 3.2)中,我正在尝试一种不同于默认模型的模型结构,想法是这样的,模型的所有相关代码都在一起,每组使用相同的支持文件命名:
app/
└── models/
├── accounts
│ ├── account.rb
│ └── support
│ └── greetable.rb
└── users
├── user.rb
└── support
└── greetable.rb
这是我如何想象这个设置的文件:
# models/accounts/account.rb
class Account < ApplicationRecord
include Greetable
end
# models/accounts/support/greetable.rb
module Greetable
def greet
"Hello, Account!"
end
end
# models/users/user.rb
class User < ApplicationRecord
include Greetable
end
# models/users/support/greetable.rb
module Greetable
def greet
"Hello, User!"
end
end
知道如何为这个设置定义autoload配置吗?希望Zeitwerk能发挥它的魔力,自动找到最近的Greetable模块,但这不是它的工作原理。
非常感谢围绕这个主题的所有想法/想法/讨论。
2条答案
按热度按时间fbcarpbf1#
Zeitwerk的基本前提是根目录(在Rails中称为“autoload path”)代表一个具体的、固定的名称空间,默认情况下,该名称空间是顶级名称空间
Object
。子树中的期望命名是相对于根的,因此,在默认设置下,
app/models
是Object
,app/models/accounts
是Accounts
。Zeitwerk思想的一个特点是出于组织的目的将文件分组在一起,而不引入名称空间,这就是折叠。
你想要实现的是可能通过折叠(未经测试):
正如文档所述,这些glob模式在 Boot 时进行评估,并在每次重新加载时再次评估,因此如果您在
app/models
下添加新组,它们将被选中。2guxujil2#
你不需要配置任何东西,你只需要理解它是如何工作的。
Zeitwerk的工作方式是,它期望自动加载根目录(任何子文件夹或app和
/app/models/concerns
,/app/controllers/concerns
)的子目录中的任何文件都嵌套在一个模块(或类)中,并根据文件夹命名:Zeitwerk会自动创建隐式命名空间(模块),因此即使您的文件只包含:
Zeitwerk会将常量嵌套为
Users::Support::Greetable
,我猜这“不起作用”,因为您希望Greetable
位于顶级名称空间中。这不仅是Zeitwerk所期望的,也是其他开发人员所期望的,并且是组织代码的公认方法,因为模块嵌套提供的封装可以防止冲突。这实际上也不是Zeitwerk所独有的--它实际上只是在Zeitwerk发明之前很久就使用的惯例。
在Rails中,把所有东西都放到全局名称空间中是我们出于方便而做的事情,而忽略了在我们脑后响起的警钟,这远非组织代码的理想方式。
虽然从组织的Angular 来看,您可以通过使用折叠或添加额外的自动加载根来使这个嵌套文件常量成为顶级常量,但我真的很想知道,为什么您要违反这样的最小惊喜原则,因为它没有提供任何实际好处。