【问题标题】:Ruby: send(method) with variable params?Ruby:带有可变参数的发送(方法)?
【发布时间】:2019-04-05 18:51:04
【问题描述】:

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

我已经找到了一种从另一个 ( send_data ) 方法 (使用 send) 中发送方法 ( api_call ) 的方法,该方法也输入到记录器中.这似乎是一个很好的关注点分离。但是,我不知道如何将必要的参数应用于我要发送的方法。

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

如果我不包含参数,我显然会收到“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

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

【问题讨论】:

  • 所有arguments关键字参数都和api_call一样吗?他们都是有位置的吗?两者兼而有之?
  • 我不确定这段代码应该如何工作。 send_data 应该打电话给api_call 还是反之亦然?如果是这样,该调用在哪里发生?你想传递什么样的“参数”,这些“参数”来自哪里?查看程序的(可能是简化的)当前版本肯定会有所帮助,即工作代码。
  • @muistooshort 我更喜欢关键字参数,但可以选择位置版本。
  • @Stefan send_data 调用 api_call。我至少想使用以下参数: - endpoint_url - 资源(即“案例”或“用户”或“文档”) - 方法(发布或获取)以便使用“通用”api_call 方法来检索各种资源(而不是几种资源的几种方法)。

标签: ruby api send


【解决方案1】:

您问题中的方法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)

【讨论】:

  • 谢谢!我会试试看!
【解决方案2】:

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

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

如果我不包含参数,我显然会收到“0 for n”错误。

尝试指定当前方法的所有参数,看起来好像错过了endpoint_URL:

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

【讨论】:

  • 谢谢,我试试看!
猜你喜欢
  • 2013-03-24
  • 1970-01-01
  • 2013-05-13
  • 2011-11-15
  • 2016-12-01
  • 2013-04-07
  • 1970-01-01
  • 2016-07-18
  • 2019-07-02
相关资源
最近更新 更多