2010-08-27 67 views
22

我在Rails中有一個更概念性的問題......或者Ruby的那個問題:什麼時候在Rails中調用「require」?

最好是在需要它的方法之前調用require權限,在類的開始處或者在某處Rails啓動時的初始化程序?

從性能的角度來看它有什麼關係?從可讀性的角度來看?如果我使用Rails 3,它會有所作爲嗎?

謝謝!

回答

19

如果你關心性能,那麼你應該在需要它的地方需要一些東西,這樣如果你的代碼部分沒有被執行,庫就不會被加載。由於該文件已被加載,因此對require的任何後續調用都不起作用。這最終看起來像沿着線的東西:

if (user.using_openid?) 
    require 'openid' 

    # ... Do OpenID stuff 
end 

雖然這是在資源方面更有效,它可以使人們很難確定應用程序的依賴關係。聲明這些預先向其他維護軟件的人員說明。請記住,當你忘記了應用程序的某些細節時,「其他人」總是包含你的未來自我。

您在技術上允許在任何時間,遲到或早期需要任何東西,但從設計的角度來看,預先聲明您的需求是更好的。如果您發現有一個元素只是間歇性使用,並且需要花費不尋常的時間或內存來加載,那麼您應該在需求文件中預先記錄該元素。例如:

require 'library1' 
require 'library2' 
require 'library3' 
require 'library4' 
require 'library5' 

# Other libraries loaded as required: 
# * slowimagelibrary 
# * slowencryptionlibrary 
# * openid 

可以說這是不太有bundler的問題,因爲你可以有你的寶石宣佈了前面更正式和實際require調用可以晚一點。

+2

謝謝tadman,這符合我的想法。結論:除了使用重要要求時,可讀性比性能更重要。 – Cimm 2010-08-27 20:06:35

4

如果你考慮vanilla Ruby,'require'主要用在第一行,因爲你確定你有權訪問你需要的東西,並且它更容易找到並閱讀你需要的依賴關係。

有幾種情況只需要在一個方法中加載一個gem,因爲腳本不是真的需要工作(例如:可選的可視化)。

隨着Rails,我相信這取決於你想要做什麼。

如果你使用Bundler,你可以假設你的gem是'required'(你當然可以用require選項覆蓋它)。

如果它是一些你想在服務器啓動時自動加載的東西(如驗證器或表單構建器),那麼你應該看看如何處理配置(autoload_paths和eager_load_paths)。

require還可以用來加載一個寶石的一部分,就像它的一個擴展。那麼它當然需要配置的位置。

如果您在多線程環境中工作,您可能會擔心,因爲它們存在一些問題。在線程運行之前,您必須確保一切都已加載。 (像類常量被加載,但方法尚未,有一篇很好的文章,但我找不到它了)。

您可能還想嘗試{Module,Kernel}。自動加載,Rails廣泛使用它來加載訪問時只需要的東西(但它看起來相當醜陋)。你也可以用const_missing自己破解它(如果你接受一個結構,這可以做簡單的延遲加載)。 這是一個簡單的例子(不適用於嵌套類)。

def Object.const_missing c 
    if (file = Dir["#{c.downcase}.rb"]).size == 1 
    require_relative(file) 
    end 
    if const_defined? c 
    const_get c 
    else 
    super # Object < Module 
    end 
end 

關於性能,需要調用相對昂貴,所以如果你知道你要使用它,做它只有一次,如果可能的。但是,要管理項目中的複雜依賴關係,可能需要相關文件。然後require_relative是1.9的方式。

最後,對於一個項目,我建議在lib /中的主文件中需要所有的文件,並且有一些Dir["**/*.rb"]表達式。你很少需要require_relative,因爲只有當你在類的主體中引用另一個常量時才需要它(方法的所有內容都沒有解決,所以沒有問題)。

另一種解決方案是在主文件中定義這些常量,它也會給你一個結構的概念。

相關問題