2015-07-19 65 views
-1

我想在來自不同來源的數據塊中運行同一個進程。我從中獲取要搜索的元素的方法具有不同的名稱。這是我想要做的一個例子:從`object.method`發送一個方法字符串

def search_in(list, i) 
    send(list) { |s| puts s if s.include?(i) } 
end 

然後,我想叫它像下面這樣:

search_in("contents.each", i)search_in("@things.entries", i)

+2

您的問題是什麼? – sawa

+0

爲什麼你現在的解決方案沒有工作? – Rots

+0

@sawa我不知道如何實現這一點,因爲send不允許將目標對象的名稱放入其參數中。 – MichelPeseur

回答

0

send只是發送消息(方法調用)一個接收器。你指定接收器作爲字符串的一部分,這意味着你必須做一些巫術來正確提取它。不過,你可能正在做一些你不應該在這裏的事情 - 我鼓勵你詳細說明你的問題,以獲得有關如何重構它以避免此特定操作的建議。

但是,要解決這個問題,您需要提取並解析接收者,提取消息,然後將消息發送給接收者。你應該避免評估。

給定一個字符串,list

# Split the string into something that should resolve to the receiver, and the method to send 
receiver_str, method = list.split(".", 2) 

# Look up possible receivers by looking in instance_methods and instance_variables. 
# Note that this isn't doing any constant resolution or anything; the assumption 
# is that the receiver is visible in the current scope. 
if instance_methods.include?(receiver_str) 
    receiver = send(receiver_str) 
elsif instance_variables.include?(receiver_str) 
    receiver = instance_variable_get(receiver_str) 
else 
    raise "Bad receiver: #{receiver_str}" 
end 

receiver.send(method) {|s| ... } 

考慮到這是一個靜態塊,雖然,你期望一個可枚舉傳遞;而不是傳遞字符串來解析爲接收方和方法,您應該嘗試通過Enumerable本身:

def search_enumerable_for(enum, i) 
    enum.each {|e| puts e if e.include?(i) } 
end 

search_enumerable_for(contents, value) 
search_enumerable_for(@things.entries, value) 
+0

謝謝你的解釋,克里斯。事實上,我正在製作一個播放列表管理器,我想要有兩個功能:將歌曲添加到播放列表中,並從播放列表中刪除歌曲。這將需要在參數中的歌曲標題,但我的代碼添加和刪除非常相似(有一個菜單來處理多個匹配等),除了兩個元素。特別是,它在刪除時搜索播放列表中的匹配項,並在添加時將整個歌曲數據庫中的匹配項放入數組中。所以我想通過創建一個名爲不同的函數來避免代碼重複,因爲每個函數的長度都是40行。 – MichelPeseur

+0

在這種情況下,只需使您的方法接受包含歌曲列表的對象並對其執行操作,而不是指代您的代碼中引用對象的字符串。 –

相關問題