我想在來自不同來源的數據塊中運行同一個進程。我從中獲取要搜索的元素的方法具有不同的名稱。這是我想要做的一個例子:從`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)
我想在來自不同來源的數據塊中運行同一個進程。我從中獲取要搜索的元素的方法具有不同的名稱。這是我想要做的一個例子:從`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)
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)
謝謝你的解釋,克里斯。事實上,我正在製作一個播放列表管理器,我想要有兩個功能:將歌曲添加到播放列表中,並從播放列表中刪除歌曲。這將需要在參數中的歌曲標題,但我的代碼添加和刪除非常相似(有一個菜單來處理多個匹配等),除了兩個元素。特別是,它在刪除時搜索播放列表中的匹配項,並在添加時將整個歌曲數據庫中的匹配項放入數組中。所以我想通過創建一個名爲不同的函數來避免代碼重複,因爲每個函數的長度都是40行。 – MichelPeseur
在這種情況下,只需使您的方法接受包含歌曲列表的對象並對其執行操作,而不是指代您的代碼中引用對象的字符串。 –
您的問題是什麼? – sawa
爲什麼你現在的解決方案沒有工作? – Rots
@sawa我不知道如何實現這一點,因爲send不允許將目標對象的名稱放入其參數中。 – MichelPeseur