我正在浏览this gem的源代码,我发现使用content_tag会让我感到困惑。
def render(view)
view.content_tag(name, attributes[:content], attributes.except(:content))
end
我不明白为什么在视图上调用content_tag。我通常使用它来帮助生成HTML标记,但我从未将其称为方法。
答案 0 :(得分:2)
最常见的是,在视图的上下文中调用content_tag
- 因此,您不需要调用view.content_tag
,因为该视图知道如何回复content_tag
(而简单地调用content_tag
与调用self.content_tag
相同。
您显示的render
方法存在于继承自MetaTag
的班级Tag
中。 Tag
是一个普通的旧Ruby对象(PORO),所以它不知道如何回应content_tag
。
但是,正如您所看到的,render
方法将视图作为参数。当然,view
对象知道如何回复content_tag
。因此,调用view.content_tag
是MetaTag
能够呈现内容标记的方式。
这几乎是Presenter模式的一个实例(不同的人使用不同的术语)。 Ryan Bates在here上有一个很好的RailsCast。
对于你在评论中提出的问题,Rails并不知道" view
是ActionView::Base
的一个实例。您有责任传入实际的视图实例。我倾向于传入控制器,以便我可以访问视图和参数。也许是这样的:
class FooController < ApplicationController
def foo_action
FooPresenter.present(self)
end
end
和...
class FooPresenter
class << self
def present(controller)
new(controller).present
end
end # class methods
#===================================================================
# instance methods
#===================================================================
def initialize(controller)
@controller = controller
end
def present
content_tag :div, data: {foo: params[:foo]}, class: 'bar'
end
private
def controller() @controller end
def view() controller.view_context end
def params() controller.params end
def method_missing(*args, &block)
view.send(*args, &block)
end
end
通过加入method_missing
方法,我不再需要致电view.content_tag
。我可以致电content_tag
。 FooPresenter无法找到该方法,因此会将调用发送到view
,其中将找到并执行该方法。
再一次,Ryan在解释所有这些方面做得很好。
答案 1 :(得分:1)
content_tag
类是ActionView::Helpers::TagHelper
类中的一种方法。我相信这堂课#39;对象自动包含在Rails视图中,或者Rails视图对象委托给该对象。
此特定gem将ActionView::Base
对象作为其render
方法的参数,以便该方法可以访问content_tag
方法,该方法是ActionView::Helpers::TagHelper
的一部分。这是Dependency Injection的一个很好的例子,这是面向对象编程的基本原则。