2010-12-16 19 views
14

我是猴子修補的東西,如一個Rails引擎:如何猴子補丁程序在Rails中自動加載的代碼?

SomeClass.class_eval do 
    # ... 
end 

我第一次打的網站中,在發展模式至少,它的工作原理,但它就像我的補丁,第二次根本不存在。我認爲它是Rails自動重新加載引擎(安裝在供應商/),而不是重新加載我的代碼。這是Rails 2.3。

任何想法如何做到這一點,使我的代碼也重新加載?

+0

我碰到過類似的問題,唯一可以解決的方法是通過在開發機器上運行導軌生產模式:(。我也對此感興趣。 – kikito 2010-12-16 12:40:29

+0

@egarcia:哎喲,我希望這次能找到更好的解決方案。 – Pablo 2010-12-16 12:42:08

+0

你如何運行你的代碼,是webbrick,mongrel還是passenger?請發佈rails和服務器版本。 – mpapis 2010-12-20 23:15:43

回答

0

不幸的是,沒有辦法掛鉤Rails 2.x的重載機制。 你可以做的是將你的補丁放在應用程序或lib目錄中的某個地方。 (lib/core_ext可能是首選位置)。然後將該目錄添加到配置中的autoload_paths。

您可能還需要打開該類,而不是使用class_eval。

+0

monkey-patch已經在lib /上,它已經在Rails 2上的autoload_paths中。我不確定爲什麼,但是用class關鍵字而不是class_eval結果打開該類成爲一個錯誤,稍後拋出一個異常。 – Pablo 2010-12-16 13:01:12

4

如果將修補程序放在/ config/initializers中的任何.rb文件中,它應該可以工作。

+0

使用class_eval和to_prepare有什麼區別? – montrealmike 2013-10-14 16:29:10

0

這很醜陋,但我發現如果我將這種代碼放在environments.rb的底部,它始終保證啓動時的正確加載順序。

18

編輯:此解決方案僅適用於Rails 3+,因爲它依賴於Rails :: Railtie中的某些功能。將此代碼放入初始化程序中。

這個問題是很老,但這裏有一個解決方案,我發現:

Rails.configuration.to_prepare do 
    SomeClass.class_eval do 
    # ... 
    end 
end 

這迫使Rails的重新加載在發展模式,每個請求的類,但只生產一次。

+0

這對Rails 3完全適合我。謝謝。 – 2011-10-06 14:32:38

+0

這也適用於Rails 4 – ABMagil 2014-10-27 14:32:13

+1

在Rails 5中爲我工作。 – ttotherat 2017-03-28 17:46:41

5

我剛寫了我的第一個猴子補丁,所以需要圍繞它制定一套約定。這是我想出的:

  1. 請將您的擴展名放在lib/ext/之下。 (由#rubyonrails IRC房間老將workmad3建議)就我而言,我加入一個方法到Mail::Message類(從mail寶石,由使用的ActionMailer),所以我創建:

    /lib/ext/mail/message.rb

  2. 打開類或模塊,並添加代碼:

    module Mail class Message def to_is_phone? !!(self.to.first =~ /^\+1\d{10}$/) end end end

  3. 創建initalizer加載所有的猴子補丁。 Rails會在引用常量時自動加載文件,但由於您將方法添加到現有的類/模塊而不是定義新的類,所以這不起作用,因此您必須手動需要所有的猴子補丁。因此,我創建:

    /config/initializers/monkey_patches.rb

    其中包含:

    require 'ext/mail/message'

+0

請注意,我目前正在使用Rails 4.1,但我認爲這也適用於舊版本。 – odigity 2014-04-14 17:52:58

+3

'monkey_patches.rb'can可以代替'Dir [Rails.root.join('lib/ext/*。rb')]。each {| file |需要文件}'並且所有的猴子補丁都會被拾取。 – dankohn 2014-10-27 03:09:38