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

谢谢!

【问题讨论】:

    标签: ruby-on-rails ruby class module routes


    【解决方案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 没关系,它只需要生成命名空间...?
    猜你喜欢
    • 1970-01-01
    • 2014-10-20
    • 1970-01-01
    • 2010-10-22
    • 2010-11-01
    • 2014-11-15
    • 1970-01-01
    • 2014-11-26
    • 1970-01-01
    相关资源
    最近更新 更多