2011-06-17 62 views
2

所以我有一個Rails 3.0引擎(寶石)。Rails3引擎幫手覆蓋

它提供在應用程序/控制器/ advanced_controller.rb的控制器,並在應用程序/助手/ advanced_helper.rb一個corresonding幫手。 (當然還有一些意見)。

到目前爲止,控制器/助手/視圖只是在使用gem的應用程序中自動提供,非常棒。

但我想讓從AdvancedHelper本地應用選擇性超馳輔助方法在發動機(理想情況下可以稱之爲「超級」)。這是一個非常合理的事情,想要允許,對,一個完全合理的(我認爲普通的)設計?

問題是,我似乎無法找到任何方法使其工作。如果應用程序定義了它自己的app/helpers/advanced_helper.rb(AdvancedHelper),那麼引擎中的一個永遠不會被加載 - 所以如果您想要替換那裏的所有幫助器方法(不需要調用super) ,但是如果你只是想超過一個,那就不行了。

所以這種說法實際上是有道理的,所以我選擇了一個不同的名字。讓我們調用我的本地./app/helpers/local_advanced_helper.rb(LocalAdvancedHelper)。如果我在那裏放置了一個不在原始引擎的AdvancedHelper中的方法,那麼這個幫助程序就會被加載,它可用於視圖。

但是,如果我把一個方法有相同名稱爲一體,在發動機的AdvancedHelper ......我的本地一個永遠不會被調用。這就像AdvancedHelper(來自引擎)在調用鏈中比LocalAdvancedHelper(從應用程序)更早。事實上,如果我打開調試器,並查看helpers.ancestors,那正是發生了什麼事情,它們與我想要的祖先鏈相反。因此,AdvancedHelper(來自引擎)在理論上可以稱爲'超級'來調用LocalAdvancedHelper(從應用程序) - 但這當然不會有很多意義,你永遠不會想這樣做。

但我想做的事......我不能這樣做。

任何人有任何想法,有沒有辦法提供這樣的設計,這似乎是完全合理的我,其中一個應用程序可以有選擇地從發動機過騎helper方法?

任何人有任何解釋爲什麼它的工作方式是?我試着看着實際的Rails源代碼,但很快就迷失了方向,圍繞這個東西的代碼在一堆地方中是非常抽象的。

這是相當深奧的問題,我很悲觀,任何人都會有任何想法,我希望你驚喜!

==更新

好吧,爲了瞭解被稱爲什麼Rails代碼部分在哪裏,我把「高清self.included;調試;年底」每個我的助手,然後在調試器我可以引發異常來查看堆棧跟蹤。

這仍然心不是」真正幫助我得到它的底部,Rails代碼跳過所有的地方,是非常令人迷惑。

但很明顯,具有'標準'名稱的助手(即WidgetController的WidgetHelper)由不同的rails代碼調用,以包含在給定控制器的'master'視圖幫助器模塊中,而不是其他幫助器。我想知道如果我給這個助手一個不同的名字,然後用(「助手OtherNamedAdvancedHelper」)手動將它包含在我的控制器中,如果這會改變加載順序的話。

+0

這是否幫助:http://stackoverflow.com/questions/3468858/rails-3 -0引擎 - 執行代碼,在-的ActionController – Kris 2012-03-19 11:16:38

回答

0

感謝您的闡述。我認爲這確實是一個問題。它仍然存在於Rails 3.2.3中,所以我提交了an issue

最不聞的解決方法,我想出了是做一個「半別名方法鏈」:

module MountedEngineHelper 
    def advanced_helper 
    ... 
    end 
end 

module MyHelper 
    def advanced_helper_with_extra_behavior 
    advanced_helper 
    extra_behavior 
    end 
end 

明顯的缺點是,你必須改變你的模板,讓你的助手叫。至少,你在那裏明確地存在額外的行爲。

1

我們可以使用Module#class_eval覆蓋。

在主應用程序,

MountedEngineHelper.class_eval do 
    def advanced_helper 
    ... 
    end 
end 

在發動機助手這樣定義的其他方法仍然可用。