在更改了数量和类型后,如何优雅地处理方法参数?

时间:2016-09-13 08:56:29

标签: ruby ruby-on-rails-4

我想将save_form_data方法与新签名一起使用。但是目前我的服务器在其队列中有很多工作依赖于旧签名 - 服务器知道该方法有2个参数,但新签名只接受一个参数。

# new signature
# params: Hash
def save_form_data(params)
  process(params['catcher_token'], params['form_data'])
end

# old signature
# catcher_token: String, form_data: Array
def save_form_data(catcher_token, form_data)
  process(catcher_token, form_data)
end

我认为我需要使用必须接受2个参数的版本来更改新签名方法。然后在其中我可以检查params是否为Hash类型,如果是,则忽略foobar。但它只能解决问题的一半,因为类型为save_form_data(params)的新调用现在将失败(我认为),因为方法接受2个参数,而不是1 ...

# modified new signature method
def save_form_data(params, foobar)
  if params.class == Hash
    process(params['catcher_token'], params['form_data'])
  else
    process(params, foobar)      
  end
end

3 个答案:

答案 0 :(得分:3)

只需为第二个参数设置默认值:

def save_form_data(params, foobar = nil)
  case params
  when Hash
    process(params['catcher_token'], params['form_data'])
  else
    process(params, foobar)      
  end
end

答案 1 :(得分:2)

正确。您需要制作兼容的签名。并区分方法内部的新旧格式。一段时间后,您将能够删除此compat图层(完成所有旧作业后)。

另外,不要使用具体的班级检查。做"是"检查。

if params.is_a?(Hash)

此代码也适用于哈希的子类(例如HashWithIndifferentAccess),而您的代码则不行。

答案 2 :(得分:2)

我使用*argscase语句来显式处理不同数量的参数。像这样:

def save_form_data(*args)
  case args.size
  when 1
    process(args[0]['catcher_token'], args[0]['form_data'])
  when 2
    process(args[0], args[1])
  else
    raise ArgumentError, "wrong number of arguments (#{args.size} for 1..2)"
  end
end

您还可以添加弃用警告:

when 2
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
    Passing `catcher_token` and `form_data` separately to `save_form_data` is
    deprecated, please pass the `params` Hash instead.
  MSG
  process(args[0], args[1])

或输入验证:

when 1
  raise TypeError, "expected Hash, got #{args[0].class}" unless args[0].is_a?(Hash)