2010-10-01 36 views
2

我正在生成一些方法。方法體根據一定的標準而變化。 我是依靠class_eval生成條件代碼。define_method塊中的條件代碼

%Q{ 
    def #{name} 
    #{ 
    (name != "password") ? "attributes[:#{name}]" : 
         "encrypt(attributes[:#{name}])" 
    } 
    end 
} 

最近我已經開始使用define_method了。如何在使用define_method時生成條件代碼塊?

編輯1

這裏是我已考慮可能的方法:

1)在運行時檢查上的名稱:

define_method(name) do  
if name == password 
    decrypt(attributes[name])  
else 
    attributes[name] 
end 
end 

這不是一個優選的方法爲該檢查在運行時完成。

2)有條件地定義整個方法。

if (name == "password") 
define_method(name) do  
    decrypt(attributes[name])  
end 
else 
define_method(name) do  
    attributes[name] 
end 
end 

這種方法具有不必重複碼塊只是改變一小部分(如我的實際方法具有幾行代碼)的缺點。

回答

3

我想是因爲封閉的,你可以做這樣的事情:

define_method name do 
    if name=='password' 
     decrypt(attributes[name]) 
    else 
     attributes[name] 
    end 
    end 

但問題是存在的,如果將在每次調用方法進行評估。 如果您想避免這種情況,您需要將不同的塊傳遞給define_method以獲得不同的行爲。例如

if name=='password' 
    define_method(name) { decrypt(attributes[name]) } 
else 
    define_method(name) { attributes[name] } 
end 

或者您可以通過由if語句選擇的lambda

define_method(name, name=='password' ? lambda { decrypt(attributes[name]) } : lambda { attributes[name] } 

有一件事要考慮,define_method可能比使用eval慢。

+0

+1,我已經考慮過您提出的兩種方法。由於顯而易見的原因,我拒絕了第一種方法。第二種方法是我現在正在做的,但我必須重複我的代碼兩次。我添加的實際方法有更大的方法體。所以它是一個眼睛疼痛。 – 2010-10-01 03:44:20

+0

我對最後一句很好奇,你有沒有關於這個問題的鏈接? – 2010-10-01 03:45:58

+0

經過一番搜索之後,它看起來比使用'def'慢了一點,但eval並非完全不同。儘管我沒有找到任何最新的基準測試,而且這樣的測試依賴於解釋器。 – BaroqueBobcat 2010-10-01 14:53:37