Rails使用什么Ruby技术来使我的控制器方法呈现视图?
只是好奇是否有人知道在Rails框架中使用什么Ruby技术来完成以下操作。
如果我不在Rails控制器上编写index
方法,如果URL匹配该路由,Rails仍将呈现索引视图文件。 这是有道理的,因为我的控制器inheritance自父类,父类必须有自己的index
方法。
但是,如果我确实定义了一个index
方法,并且只告诉它设置一个实例变量,它仍会呈现相应的视图。 例如:
def index @weasels = Weasel.all # If I omit this line, Rails renders the index anyway. # If this behavior is defined in the parent class's index method, # it seems that by overriding the method, my index wouldn't do it. # I'm not explicitly calling super to get the method from # ActionController::Base, but maybe Rails is doing something like that? render :index end
在纯Ruby中,我希望必须调用super
才能获得该行为。
我假设Rails使用某种元编程技术来保证我的控制器方法会调用super
。 如果是这样,有人可以解释一下吗? 你能指出这样做的源代码吗?
更新
正如MladenJablanović指出的那样,我最初的心理模型是错误的; 控制器方法通常不会呈现视图; 相反,控制器方法和视图呈现都由一些框架代码调用。 这很明显,因为我可以创建一个具有任何名称的控制器方法 – 例如, search
– 并且将呈现search
视图。 很明显,在这种情况下,我没有覆盖父方法,并且一些框架代码正在解析控制器方法名称并查找匹配的视图。
但是,框架必须能够检测控制器方法是否已经调用了render
。 这对我来说是另一个小谜。
在控制器上,有一个名为render_for_text
的方法。 这需要一个字符串并将结果设置为响应主体。 即使您不渲染为文本,渲染视图文件也只是读取文件的内容,对其进行评估,然后将其传递给render_for_text
方法。 然后该方法将一个名为@performed_render
的实例变量@performed_render
为true
,告诉rails控制器已经呈现了一个视图。
那么有一个叫做的方法performed?
表示是否已调用渲染动作。 它通过检查@performed_render
或@performed_redirect
是否为真来完成此操作。
有了上面的信息, 渲染方法的第一行现在应该有意义,并希望回答你的问题:
raise DoubleRenderError, "Can only render or redirect once per action" if performed?
在渲染视图时,Rails使用控制器中的实例变量的副本初始化相应视图模板的实例。 因此,实例变量实际上并不是由视图inheritance的,而是在呈现视图之前从控制器复制到视图中。
我没有查看源代码中的确切细节,但上面的解释至少应该概述它是如何工作的一般概念。
几年前Jamis Buck写了很多关于隐式路线的文章。
我相信你要找的代码在参考资料中 。 Rails查看入站请求,并且(对于RESTful路由)在此处确定控制器和操作(如果未指定)。
更新:控制器是Rails框架中非常复杂的部分。 它不像单个Ruby类一样简单(这就是为什么不需要super
,而是调用单个方法之前和之后的一系列调用)。
Rack处理请求并将其传递给执行路由的Rails,委托给ActionController的实例进行操作(可能已经编码,也可能没有编码),然后将结果传递给渲染过程。
- Rails教程sample_app在Heroku中失败,带有log:ActionController :: RoutingError(没有路由匹配“/ about”):
- Railsunit testing不会加载灯具
- Rails 3:路由错误 – 未初始化的常量MyController :: Google
- 如何使用mysql安装Ruby on Rails并使其正常工作,一步一步指导?
- 为什么Rails可以使用`if`作为哈希键而不是Ruby
- 如何裁剪然后使用Paperclipresize
- 如何使用Minitest为Devise测试控制器sign_in
- 通过Capybara(v2)与Bootstrap模态进行交互时遇到问题
- 使用OpenURI或net / http进行Ruby代理身份validationGET / POST