2014-02-27 50 views
1

所以我有一個gem包含一些activerecord模型,它們被我們平臺上的多個應用程序使用。我們有一個不斷定義的「類型」列表,這些列表在不同的應用程序上有所不同。在導軌模型中重新定義寶石方法不起作用

# in the gem 
class MyModel < ActiveRecord::Base 
    TYPES = ["A Type", "Another Type"] 
end 

在應用程序代碼中重新定義這個常量將對已經初始化的常量產生一個警告。因此,因爲它不是真的不變,所以我決定將它重構爲類方法。

# gem 
class MyModel < ActiveRecord::Base 
    def self.types 
    [] 
    end 
end 

# application a 
class MyModel < ActiveRecord::Base 
    def self.types 
    ["A Type", "D Type"] 
    end 
end 

# application b 
class MyModel < ActiveRecord::Base 
    def self.types 
    ["B Type", "C Type"] 
    end  
end 

然而,在應用程序A或B訪問MyModel.types時,類型是[]。這一點以及其他一些問題讓我得出結論:在rails應用程序加載後,gem會被加載,而我的假設恰恰相反。

什麼是處理這種不同情況的最佳方式?

回答

3

爲此在你的應用程序

config/initializers/創建一個文件,並在這兩個您的應用程序添加以下代碼

MyModel.instance_eval do 
    def types 
    ["A Type", "D Type"] 
    end 
end 

MyModel.class_eval do 
    def self.types 
    ["A Type", "D Type"] 
    end 
end 
+0

爲什麼不是'class_eval',而是'instance_eval'?... – apneadiving

+0

@apneadiving:'instance_eval'是正確的。它增加了方法本徵類的MyModel – usha

+0

老實說,我希望避免這種做法,因爲其中一個應用程序是非常大的,我想保持代碼在一個可預測的地方,但我解決了在本地類的評論重新打開和做初始化方式。謝謝 – DVG

0

您必須從您的引擎明確要求初始類,這將確保它被加載。 這有時不在發展(autoload例如)的情況下

require YourEngine::Engine.root.join('app/models/your_namespace/my_model') 

class MyModel #no inheritance here, we just reopen an existing class, right? 
    def self.types 
    [] #override it as you like 
    end 
end