2011-05-02 26 views
6

我有被延伸的另一引擎的類在其初始化像這樣的發動機:當cache_classes = false時,爲什麼在Rails引擎初始化程序中包含錯誤?

module MyApp 
    class Engine < ::Rails::Engine 
     initializer 'extend Product' do 
      AnotherApp::Product.send :include, MyApp::ProductExtender 
     end 
    end 
end 

ProductExtender模塊呼籲AnotherApp一些方法::產品時,它包含,例如

module ProductExtender 
    def self.included(model) 
     model.send :include, MethodsToCall 
    end 

    module MethodsToCall 
     def self.included(m) 
      m.has_many :variations 
     end 
    end 
end 

這工作在測試和生產環境,但是當config.cache_classes = false,它在我拋出一個NoMethodError當我嘗試調用由ProductExtender定義的東西,像@ product.variations。

不用說,看到我所有的測試都通過了,然後在開發過程中出現錯誤,這是令人不寒而慄的。當我設置cache_classes = true時,它不會發生,但它讓我懷疑我是否正在做我不該做的事。

我的問題是雙重的:爲什麼會發生這種情況,是否有更好的方法來實現在另一個應用程序對象上擴展/調用方法的功能?

謝謝大家!

回答

4

我設法解決這個問題,使用to_prepare塊代替初始值設定項。 to_prepare塊在生產中和開發中的每個請求之前執行一次,因此似乎滿足我們的需求。

我在研究Rails::Engine時並不明顯,因爲它是從Rails::Railtie::Configuration繼承的。

因此,而不是在問題的代碼,我會:

module MyApp 
    class Engine < ::Rails::Engine 
     config.to_prepare do 
      AnotherApp::Product.send :include, MyApp::ProductExtender 
     end 
    end 
end 
0

cache_classes實際上有一個令人誤解的名稱:沒有涉及緩存。如果將此選項設置爲false,則rails將顯式卸載應用程序代碼並在需要時重新加載它。這使您可以在開發過程中進行的更改生效,而無需重新啓動(服務器)進程。

在你的情況下,AnotherApp :: Product與ProductExtender一樣被重載,但初始化器在重載後不會再次被觸發,所以AnotherApp :: Product不是'extended'。

我非常瞭解這個問題,並最終以cache_classes = true運行我的開發環境,偶爾會重新啓動我的服務器。我在引擎/插件方面沒有太多的發展,所以這是最簡單的方法。

+0

感謝您的意見,@mosch。你的帖子讓我思考,所以我做了一些更多的研究,最終找到了config.to_prepare塊,它似乎解決了問題,而無需更改cache_classes設置(請參閱我提交給我自己的問題的答案)。 – joshuarh 2011-05-02 17:17:07

相關問題