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'
请注意 autoload
是 Module
上的一个方法,因此您必须将对 autoload
的调用放在同一个 'namespace' 中 - 即:
module MyApp
autoload :MyThing, 'models/my_thing'
end
将在缺少常量 MyApp::MyThing
时触发自动加载。也就是说 - 除非您 知道为什么 您需要自动加载 类,只需在文件顶部要求它。
我正在尝试设置一个新的模块化 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'
请注意 autoload
是 Module
上的一个方法,因此您必须将对 autoload
的调用放在同一个 'namespace' 中 - 即:
module MyApp
autoload :MyThing, 'models/my_thing'
end
将在缺少常量 MyApp::MyThing
时触发自动加载。也就是说 - 除非您 知道为什么 您需要自动加载 类,只需在文件顶部要求它。