Ruby: 发送(方法)可变参数?

Ruby: send(method) with variable params?

我正在开发一个小程序,用于从 post 获取 API 的多个资源。我的程序的当前版本工作正常但不是很清晰,所以现在我正在尝试重构我的代码以便更好地分离关注点(准备数据、发送数据、记录日志等)。但是现在我卡住了。

我想出了一种从另一个 ( send_data[= 中发送方法 ( api_call ) 的方法36=] ) 方法(使用发送),它也被输入到记录器中。这似乎是一个很好的关注点分离。但是,我不知道如何将必要的参数应用于我要发送的方法。

我已经尝试遵循其他一些与发送和参数相关的 Whosebug 问题和教程,但我似乎无法弄清楚如何正确地做到这一点。

如果我不包含参数,我显然会收到“0 for n”错误。如果我尝试将它们包含在发送中,我会收到一条错误消息,告诉我它不需要参数。

  1. 从 send_data 中发送 api_method 的好方法是什么,同时允许我可变地设置参数?

  2. 我是否应该将参数设置在一个数组中,然后 *splat 该数组作为参数?我不太确定我该怎么做。

  3. 这是解决这个问题的明智方法吗?我在想我还不如为不同的资源创建更多的方法,这些方法继承自 "api_call",这样我就可以摆脱大多数参数?但这似乎不是很干?

这是我的代码的一个简化示例:

class ApiConnector

  def send_data(method_name)
    begin
      @attempts += 1
      puts "#{@attempts}th attempt"
      send(method_name)     # (how) do I set params here?
    rescue Errno::ETIMEDOUT => e
      retry if @attempts < 3
    end
  end

  def api_call(endpoint_URL: , resource: 'cases' , action: nil , method: 'get', uuid: nil)
    request = Typhoeus::Request.new(
      "#{endpoint_URL}/api/v1/#{resource}/#{uuid}/#{action}",
      verbose: true,
      method: :post,
      headers: { 'Content-Type' => "multipart/form-data", "API-key" => "123", "API-Interface-ID" => "123", "User-Agent" => "AGENT" }
    )

    request.run 
  end

end

显然也欢迎任何对相关文档的引用。非常感谢。

也许最好只为这个方法使用条件:

if method == :api_call
  send method_name, endpoint_URL: __TEST_URL__, resource: 'cases' , action: nil , method: 'get', uuid: nil
else
  send method_name
end

If I don't include the params, I obviously get a "0 for n" error.

尝试为当前方法指定所有参数,看起来是遗漏了 endpoint_URL:

def api_call(endpoint_URL: _MISS_, resource: 'cases' , action: nil , method: 'get', uuid: nil)

您问题中的方法 api_call 使用 keyword arguments 的现代语法。您可以使用 send 调用此方法,并将参数作为散列传递:

params = {
  endpoint_URL: 'https://www.google.com',
  # other params
}
send(:api_call, params)

(因为 endpoint_URL 参数没有默认值,你必须传递它以避免 ArgumentError 错误)


如果该方法是使用通用位置参数编写的:

def api_call(endpoint_URL, resource = 'cases' , action = nil , method = 'get', uuid = nil)
  # ...
end

你也可以用 send 调用它,但是参数数组应该是 *splat:

params = [
  'https://www.google.com',
  # other params
]
send(:api_call, *params)