Ruby继承并要求顺序

Ruby inheritance and require order

我正在尝试设置一个新的模块化 Sinatra 应用程序。这是相关的文件夹结构:

- app 
  - controllers
    - application_controller.rb
    - website_controller.rb
  - config.ru 

application_controller.rb 定义 ApplicationController class,需要 sinatra/base,除此之外,没有做任何有趣的事情。

website_controller.rb继承application_controller.rb:

# website_controller.rb
class WebsiteController < ApplicationController

  include Sinatra::Cookies
  ...
end

我的 config.ru 文件是我 运行 启动 Sinatra 应用程序的文件,因此它应该需要所有 classes:

#config.ru
require 'sinatra/base'

Dir.glob('./app/{models,helpers,controllers}/*.rb').each {|file|
  require file
}

...

当它需要所有文件时,在需要 application_controller.rb 之前需要 website_controller.rb。这样,当解析 WebsiteController 上的继承时,它还不知道 ApplicationController 是什么,我得到错误 uninitialized constant ApplicationController (NameError).

设置我的项目的最佳做法是什么,这样我就可以准备好所有必需的文件,而不会遇到这种排序问题?

website_controller.rb 的顶部,要求 application_controller.rb

您可能觉得它多余,但这不会有害。这是最稳健的方式。

所以,另一个答案实际上是正确且最简单的方法 - 但如果出于某种原因您不想那样做,您可以使用 autoload,前提是您已经开发了 Sinatra 应用程序"modular" 风格。

config.ru 中,您目前 "eager-loading" 所有文件。相反,您将显式列出未知常量的加载路径 - 如下所示:

autoload :ApplicationController, 'app/controllers/application_controller'
autoload :WebsiteController, 'app/controllers/website_controller'

请注意 autoloadModule 上的一个方法,因此您必须将对 autoload 的调用放在同一个 'namespace' 中 - 即:

module MyApp
  autoload :MyThing, 'models/my_thing'
end

将在缺少常量 MyApp::MyThing 时触发自动加载。也就是说 - 除非您 知道为什么 您需要自动加载 类,只需在文件顶部要求它。