2010-03-22 97 views
12

我希望能實現像所有偉大的插件在那裏爲紅寶石,這樣就可以做到這一點:將參數傳遞給Ruby中包含的模塊?

acts_as_commentable 
has_attached_file :avatar 

但我有一個約束:

該助手方法可以只包含一個模塊;它不能定義任何變量或方法。

這樣做的原因是因爲我想要的選項哈希定義類似type,這可以轉換成一個說20個不同的「主力」模塊,所有這一切,我可以在一條線上總結像這樣:

def dynamic_method(options = {}) 
include ("My::Helpers::#{options[:type].to_s.camelize}").constantize(options) 
end 

那麼那些「工作母機」將處理的選項,做這樣的事情:

has_many "#{options[:something]}" 

這裏的結構是什麼樣子,我想知道,如果你知道ŧ他缺少的部分在拼圖:

# 1 - The workhorse, encapsuling all dynamic variables 
module My::Module 
    def self.included(base) 
    base.extend ClassMethods 
    base.class_eval do 
     include InstanceMethods 
    end 
    end 

    module InstanceMethods 
    self.instance_eval %Q? 
     def #{options[:my_method]} 
     "world!" 
     end 
    ? 
    end 

    module ClassMethods 
    end 
end 

# 2 - all this does is define that helper method 
module HelperModule 
    def self.included(base) 
    base.extend(ClassMethods) 
    end 

    module ClassMethods 

    def dynamic_method(options = {}) 
     # don't know how to get options through! 
     include My::Module(options) 
    end 

    end 
end 

# 3 - send it to active_record 
ActiveRecord::Base.send(:include, HelperModule) 

# 4 - what it looks like 
class TestClass < ActiveRecord::Base 
    dynamic_method :my_method => "hello" 
end 

puts TestClass.new.hello #=> "world!" 

%Q?我不完全知道如何使用,但我基本上只是想以某種方式能夠從helper方法通過options散列成主力模塊。那可能嗎?這樣,workhorse模塊可以定義各種功能,但是我可以在運行時爲變量命名。

回答

3

我的工作類似的東西,根據我看到了曾經有些聰明的Ruby代碼,但現在不能再找到。我有幾乎工作的東西,但它在你的模塊中混淆了self.included和self.extended之類的東西,因爲有些顯而易見的原因可以解決,但我不喜歡它會有多複雜。我認爲還有一個我沒有想到的技巧會讓這項工作更加完美。

因此,這可能會或可能不會爲你工作,但我想要是動態創建的基於您選擇匿名模塊的想法。 (我認爲「類型」可能是一個保留字,但我不確定,所以讓我們說「選項」)。看看這個主意:


Module HelperModule 
    def[](options) 
     Module.new do 
     include HelperModule 
     define_method(:options) { options } 
     end 
    end 

    def options 
    raise TypeError.new("You need to instantiate this module with [], man!") 
    end 
end 

obj = Object.new 
obj.extend(HelperModule) 
obj.options => raises TypeError 

obj = Object.new 
obj.extend(HelperModule[ :my_option => "my_option" ] 
obj.options => { my_option => "my_option } 

那種整潔,是吧?但是對於我來說還不夠好,因爲從HelperModule [options]得到的實際模塊沒有self.included和self.extended從原始的HelperModule。我想我可以在anon模塊中定義self.included和self.extended,但我不喜歡代碼混淆。我也不喜歡在匿名模塊中明確地說「包含HelperModule」,我寧願它是像「自我」一樣,除了「自我」並不意味着那裏是正確的事情,所以這是行不通的。

啊,等一下,你猜我剛發現:如果這個一般方法看起來像它應該爲你工作,它可以通過paramix寶石提供: http://rubyworks.github.com/paramix/

0

ActionModel寶石可以幫助你。我在我的項目中使用它。

+0

你能詳細說明在這種情況下這可能會有什麼幫助嗎?這可能是顯而易見的,但在這個網站上的好答案包括這類信息。一個沒有解釋的指針並不是一個真正的答案.... – GreenAsJade 2014-02-14 23:56:08

+0

它是acts_as對於ruby類的DSL。您可以將字段和選項傳遞給action(模塊),例如acts_as_searchable:title,ignorecase:true – 2014-02-15 00:25:18