了解 Ruby on Rails 6 中的路由 + 模块/类名称 [以及在此上下文中模块是啥]
Posted
技术标签:
【中文标题】了解 Ruby on Rails 6 中的路由 + 模块/类名称 [以及在此上下文中模块是啥]【英文标题】:Understanding routes + module/class names in Ruby on Rails 6 [and what a module is in this context]了解 Ruby on Rails 6 中的路由 + 模块/类名称 [以及在此上下文中模块是什么] 【发布时间】:2021-06-03 07:48:22 【问题描述】:如果我有一个在特定位置查找控制器操作的路由,例如:
things_path GET /things some/things#index
我可以通过以下任一方式满足这条路径:
# app/controllers/some/things_controller.rb
class Some::ThingsController
def index
# do stuff
end
end
# app/controllers/some/things_controller.rb
module Some
class ThingsController
def index
# do stuff
end
end
end
但不是:
# app/controllers/some/things_controller.rb
class ThingsController
def index
# do stuff
end
end
我不明白为什么,或者module
这个词的含义...
在我的脑海中,路由想在some
目录中找到things_controller.rb
(在自动加载的路径上,[我已指定app/controllers
])。
为什么 rails 需要我的文件内容来指定/匹配位置?
如果module Some
与Some::
具有相同的效果,这意味着模块在这里/正在做什么?它真的是一个模块...还是一个命名空间?!
谢谢!
【问题讨论】:
【参考方案1】:Ruby on Rails 使用名为Zeitwerk 的常量自动加载器。这个自动加载器加载常量,这就是你永远不必require
你自己的项目文件(在app/
中)的原因。
This autoloading system comes with some file structure constraints/pre-requisites. 例如,常量Admin::UsersController
必须在任何app/*
目录中的admin/users_controller.rb
文件中定义。
在Admin::UsersController
查找时,自动加载器将首先搜索admin.rb
。如果未找到此文件,则假定 Admin
是命名空间和 the autoloader will create the Admin
module dynamically。加载 Admin
后,自动加载器会查找 admin/users_controller.rb
。
您可以在app/controllers/some/things_controller.rb
文件中定义ThingsController
,但您必须将app/controllers/some/
标记为autoload paths,这可能不是您想要的。可以说更好的选择是将文件移动到app/controllers/things_controller.rb
。
有关自动加载器的完整说明,我建议阅读Ruby on Rails - Autoloading and Reloading Constants (Zeitwerk Mode) 指南。
两者的区别:
module Admin
class UsersController < ApplicationController
end
end
还有:
class Admin::UsersController < ApplicationController
end
是常量查找上下文。
在第一种情况下,如果您在UsersController
中使用常量。 Ruby 以下列方式查找常量:
Admin::UsersController::MY_CONSTANT
如果上面没有找到:Admin::MY_CONSTANT
如果上面没有找到:::MY_CONSTANT
(根常量)
如果上面没有找到:NameError (uninitialized constant ...)
第二种情况类似,但跳过了Admin::MY_CONSTANT
步骤,因为您没有打开Admin
模块。
请注意,以大写字母开头的任何内容都被视为常量,这可以是像上面一样的常量值(通常是全大写,但不是必需的),但类和模块也是常量(通常是驼峰式)。
有关常量查找结帐的更多信息Everything you ever wanted to know about constant lookup in Ruby
【讨论】:
非常感谢您的详细回答,真的很有帮助:) 当你说“On Admin::UsersController
查找时,自动加载器将首先搜索admin.rb
”,你的意思是它在admin.rb
中查找常量UsersController
吗?所以如果它在那里找到一个,它会停止寻找其他东西吗? (例如,永远找不到users_controller.rb
)。如果您有admin.rb
,但没有定义UsersController
,它会继续查找/仍会自动创建Admin
命名空间?
@JoshuaESummers 否。如果您访问 Admin::UsersController
,您实际上是在请求 2 个常量。首先您请求Admin
,然后您在Admin
命名空间内请求UsersController
。自动加载器期望 admin.rb
加载 Admin
模块或类。如果没有加载 Admin
常量,您将无法访问该命名空间中的任何内容。加载Admin
后,它会查找admin/users_controller.rb
以加载命名空间UsersController
。自动加载器不希望 users.rb
定义 UsersController
。
另外,当您说“在 Admin::UsersController 查找时”,这是什么意思?至于什么时候触发“查找”?例如,当有人去那条路线时会是这样吗?
re 你的第一个答案...所以如果它找到定义模块/类的admin.rb
...如果文件中没有定义UserController
没关系,它只需要生成命名空间...?以上是关于了解 Ruby on Rails 6 中的路由 + 模块/类名称 [以及在此上下文中模块是啥]的主要内容,如果未能解决你的问题,请参考以下文章