了解 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 SomeSome:: 具有相同的效果,这意味着模块在这里/正在做什么?它真的是一个模块...还是一个命名空间?!

谢谢!

【问题讨论】:

【参考方案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 中的路由 + 模块/类名称 [以及在此上下文中模块是啥]的主要内容,如果未能解决你的问题,请参考以下文章

Ruby on Rails 路由到控制器

Ruby on Rails 6 - 如何根据特定路线建模/隐藏视图?

ruby Ruby on Rails:常见路由

ruby on rails中收集路线和会员路线的区别?

Ruby on Rails 路由解析

Ruby on Rails:延迟的作业无法使用邮件程序并给出路由错误