将方法名称作为参数传递给另一个方法

时间:2016-10-06 21:41:20

标签: ruby

我想将方法​​名称而不是块作为参数传递给另一个用作回调的方法:

def one(param)
  puts param
end

def two(param, &callback)
  callback.call(param)
end

two('hi', :one)

这可能吗?我试了一下并得到一个错误,说我通过了两个参数但只有一个是预期的。

3 个答案:

答案 0 :(得分:3)

如果你想发送一个方法的名称,那么,是的,符号是正确的形式,正如John的答案所指出的那样(然后你可以使用send称这种方法)。但是,如果您愿意,您也可以发送方法本身

<div id="loginArea">
  <div id="searchForm">
    Search For Results
    <br />
    <div>
      <form id="search-form" action="/events/search" accept-charset="UTF-8" method="get">
        <input name="utf8" type="hidden" value="✓">
        <input type="text" name="first_name" id="first_name" placeholder="First Name" class="searchField">
        <input type="text" name="last_name" id="last_name" placeholder="Last Name" class="searchField">
        <input type="text" name="event" id="event" placeholder="Event" class="searchField">
        <input alt="Search" type="image" src="http://www.racertracks.com/assets/magnifying-glass-0220f37269f90a370c3bb60229240f2ef2a4e15b335cd42e64563ba65e4f22e4.png" class="search_button">
      </form>
    </div>
  </div>
</div>

这种做事方式的优点是,当方法需要块时,可以在没有(如def one(param) puts param end def two(param, &callback) callback.call(param) end one_method = method(:one) two('hi', &one_method) 的情况下)的情况下执行此操作,而无需更改方法定义。你也可以从不同的对象传递方法,而如果你想在另一个对象上调用方法,你也必须传入你想要调用它的人(或以其他方式解决这个问题) ):

two

答案 1 :(得分:2)

您想使用send

def two(param, callback)
  send(callback, param)
end

答案 2 :(得分:2)

虽然@ JohnNaegle的答案是正确的,但我发现使用#method会更加优雅地执行此操作,它会返回Method个对象。方法对象具有.call(*args)方法,但您可以传递参数。所以,用你的例子看起来像:

def one(param)
  puts param
end

def two(param, callback)
  callback.call(param)
end

two('hi', method(:one))

更改是您通过调用Method(与Object.method相同而不是字符串)传递对method实例的引用。

如果您想传递符号而不是Method,则可以使用以下版本的#two

def two_2(param, callback)
  method(callback.to_sym).call(param)
end

two_2('hi', :one)
# Or you could also pass a string or anything that #responds_to?(:to_sym)
two_2('hi', 'one')

我建议进一步改进,以便two可以接受多个参数传递给回调,然后首先列出回调,然后使用*params接收所需数量的参数。以下是一个示例(使用上面#one的定义):

def one_with_many_params(*params)
  puts params.join
end

# Improved version of two
def two_3(callback, *params)
  callback.call(params)
end

# Improved version of two_2
def two_4(callback, *params)
  method(callback.to_sym).call(params)
end

two_3(method(:one), 'hi') #=> "hi"
two_3(method(:one_with_many_params), "Hi", " my ", "name", " is ", "Foo!")
#=> "Hi my name is Foo!"

two_4('one', 'Hello!') #=> "Hello!"
two_4(:one_with_many_params, "Hi", " my ", "name", " is ", "Bar!")
#=> "Hi my name is Bar!"