2011-11-04 60 views
0

在我的應用程序中,我不得不與一些第三方軟件進行接口,希望有一天能夠替換。因此,我並沒有將所有模型數據與模型本身的第三方軟件所需的表單之間的映射關聯起來,而是爲每個模型創建了一個mapper模塊,將代碼隔離在一個簡單的地方到時候刪除。如何根據名稱自動在類中包含模塊(如助手包含在視圖中)

所以我有類似如下:

app/ 
    models/ 
    people.rb 
    mappers/ 
    people_mapper.rb 

理想情況下,我想自動包括與匹配的名稱,助手會自動包含在意見相同的方式模型類模塊同名。如何/在哪裏自動包含助手,這也是我添加自己的代碼的最佳位置?

回答

0

你可以嘗試這樣的事:

module Mapper::Core 

    def self.included(base) 
    base.extend(ClassMethods) 
    end 

    module ClassMethods 

    # model class method to include matching module 
    # this will throw an error if matching class constant name does not exist 
    def has_mapping 
     @mapper_class = Kernel.const_get("Mapper::#{self}Mapper") 
     include @mapper_class 
    end 

    # an accessor to the matching class mapper may come in handy 
    def mapper_class 
     @mapper_class 
    end 

    end 
end  

然後再requireinclude模塊中ActiveRecord::Base在初始化(請確保您Mapper模塊需要在您的「映射器」文件夾,或使用的所有文件config.autoload_paths)。

如果你不希望在所有使用has_mapping類方法,你可以嘗試重寫的ActiveRecord::Baseself.inherited回調,但它可能會變得危險:

def self.included(base) 
    base.extend(ClassMethods) 
    base.instance_eval <<-EOF 
     alias :old_inherited :inherited 
     def self.inherited(subclass) 
     subclass.has_mapping 
     old_inherited(subclass) 
     end 
    EOF 
    end 

我沒有這條老命,所以謹慎行事

編輯:

我累了,當我寫這一點。還有一個更簡單autoinclude匹配模塊方式:

module Mapper::Core 
    def self.included(base) 
    begin 
     mapper_class = Kernel.const_get("Mapper::#{base.name}Mapper") 
     base.instance_eval("include #{mapper_class}") 
    rescue 
     Logger.info "No matching Mapper Class found for #{base.name}" 
    end 
    end 
end 

與初始化這個:

ActiveRecord::base.instance_eval('include Mapper::Core') 

所有繼承類現在將include Mapper::Core,這將引發包括匹配類的。

+0

感謝您抽出寶貴時間回答 - 我認爲這不值得冒險。 – Russell

+0

是的。也這麼覺得。在重寫時忘記了調用':old_inherited',修復它。增加了另一種自動包含的方式。 –