从`object.method`字符串发送方法

时间:2015-07-19 21:10:29

标签: ruby

我希望在来自不同来源的数据块中运行相同的过程。我从中获取要搜索的元素的方法具有不同的名称。这是我想要做的一个例子:

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)

1 个答案:

答案 0 :(得分:0)

send只是向接收者发送消息(方法调用)。您将 receiver 指定为字符串的一部分,这意味着您必须执行一些操作才能正确提取它。你可能正在做一些你不应该做的事情 - 我鼓励你详细说明你的问题,以获得如何重构它以避免这种特殊操作的建议。

但是,要解决此问题,您需要提取并解析接收器,提取消息,然后将消息发送给接收方。你应该避免使用eval。

给定一个字符串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;而不是传递一个字符串来解析为接收器和方法,你应该尝试传递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)