2016-08-03 64 views
0

我在瀏覽this gem的源代碼,我發現content_tag的使用讓我困惑不已。Rails content_tag方法

def render(view) 
    view.content_tag(name, attributes[:content], attributes.except(:content)) 
end 

我不明白爲什麼在視圖上調用content_tag。我通常使用它作爲助手來生成HTML標記,但我從來沒有把它稱爲一種方法。

回答

2

最常見的,content_tag被稱爲在視圖的情況下 - 所以,你不需要調用view.content_tag,因爲該視圖知道如何來應對content_tag(和簡單地調用content_tag是與調用self.content_tag)。

您正在顯示的render方法存在於繼承自Tag的類MetaTag中。 Tag是一個普通的舊Ruby對象(PO​​RO),所以它不知道如何響應content_tag

但是,如您所見,render方法將視圖作爲參數。當然,view的對象知道如何迴應content_tag。因此,調用view.content_tagMetaTag能夠呈現內容標記的方式。

這幾乎是Presenter模式的一個實例(不同的人使用不同的術語)。 Ryan Bates在這個here上有一個很好的RailsCast。

對於你的問題在評論中,Rails不知道viewActionView::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,該方法將被發現並執行。

再一次,瑞安在解釋所有這些方面做得很好。

+0

感謝您的解釋和指向我的RailsCast。我仍然不明白一件事:Rails如何知道'view'是Rails視圖的'ActionView :: Base'視圖實例? – davideghz

+0

您的更新回答很好,但是您能否指出我在ActionView :: Base實例實際傳遞給方法的鏈接源代碼(gem)中的確切行? – davideghz

+1

哇!你真的讓我爲這個工作......(開玩笑)。因此,在參考創業板的仔細檢查,文檔提供**使用控制器元標記**和**鑑於**使用元標籤 - 這表明,這並不遵循PORO演示模式(我們對此深感抱歉)。相反,MetaTag方法通過'meta-tags/lib/meta_tags.rb'的第36和37行調用的包含方法包含在'ActionController :: Base'和'ActionView :: Base'中。在這些情況下,'view'始終可用。謝謝:) – jvillian

1

不用過多的細節,content_tagActionView::Helpers::TagHelper類中的方法。我相信這個類的對象要麼自動包含在Rails視圖中,要麼Rails視圖對象委託給這個對象。

這種特殊的寶石需要一個ActionView::Base對象作爲參數用於其render方法,以便該方法可以訪問content_tag方法,該方法是ActionView::Helpers::TagHelper一部分。這是一個體面的Dependency Injection的例子,這是面向對象編程的基本原理。