我正在尝试建立一个新的模块化Sinatra应用程序。这是相关的文件夹结构:
- app
- controllers
- application_controller.rb
- website_controller.rb
- config.ru
application_controller.rb
定义ApplicationController
类,需要sinatra/base
,除此之外,不做任何有趣的事情。
website_controller.rb
继承application_controller.rb
:
# website_controller.rb
class WebsiteController < ApplicationController
include Sinatra::Cookies
...
end
我的config.ru
文件是我为启动Sinatra应用而运行的,所以应该要求所有类:
#config.ru
require 'sinatra/base'
Dir.glob('./app/{models,helpers,controllers}/*.rb').each {|file|
require file
}
...
如果需要所有文件,则在需要website_controller.rb
之前需要application_controller.rb
。这样,当解析WebsiteController
上的继承时,它还不知道ApplicationController
是什么,我得到错误uninitialized constant ApplicationController (NameError)
。
设置项目的最佳做法是什么,以便在不遇到这种排序问题的情况下准备好所有必需的文件?
答案 0 :(得分:3)
所以,另一个答案实际上是正确和最简单的方法 - 但如果由于某种原因您不想这样做,您可以使用autoload
,前提是您已经开发了Sinatra应用程序“模块化”风格。
在config.ru
中,您目前正在“急切地”加载所有文件。相反,您将明确列出未知常量的加载路径 - 如下所示:
autoload :ApplicationController, 'app/controllers/application_controller'
autoload :WebsiteController, 'app/controllers/website_controller'
请注意,autoload
是Module
上的一种方法,因此您必须将autoload
的调用放在同一个“命名空间”中 - 即:
module MyApp
autoload :MyThing, 'models/my_thing'
end
当缺少常量MyApp::MyThing
时将触发自动加载。这就是说 - 除非你知道为什么你需要自动加载你的类,只需要在文件顶部需要它。
答案 1 :(得分:2)
在website_controller.rb
的顶部,需要application_controller.rb
。
你可能觉得它多余,但这不会造成伤害。这是最强大的方式。