是的,这是可能的,但不是很优雅。
您必须使用the parameters method,它返回方法参数及其类型的数组(在这种情况下,我们只有关键字参数)。
def foo(one: 1, two: 2, three: 3)
method(__method__).parameters
end
#=> [[:key, :one], [:key, :two], [:key, :three]]
知道这一点后,有多种方法可以使用该数组来获取所有参数及其提供的值的哈希值。
def foo(one: 1, two: 2, three: 3)
params = method(__method__).parameters.map(&:last)
opts = params.map { |p| [p, eval(p.to_s)] }.to_h
end
#=> {:one=>1, :two=>2, :three=>3}
所以你的例子看起来像
def method(name: nil, color: nil, shoe_size: nil)
opts = method(__method__).parameters.map(&:last).map { |p| [p, eval(p.to_s)] }.to_h
SomeOtherObject.some_other_method(opts)
end
仔细考虑使用它。它很聪明,但以可读性为代价,其他阅读您的代码的人不会喜欢它。
您可以使用辅助方法使其更具可读性。
def params # Returns the parameters of the caller method.
caller_method = caller_locations(length=1).first.label
method(caller_method).parameters
end
def method(name: nil, color: nil, shoe_size: nil)
opts = params.map { |p| [p, eval(p.to_s)] }.to_h
SomeOtherObject.some_other_method(opts)
end
更新: Ruby 2.2 引入了Binding#local_variables,可以用来代替Method#parameters。请小心,因为在方法内定义任何其他局部变量之前,您必须调用 local_variables。
# Using Method#parameters
def foo(one: 1, two: 2, three: 3)
params = method(__method__).parameters.map(&:last)
opts = params.map { |p| [p, eval(p.to_s)] }.to_h
end
#=> {:one=>1, :two=>2, :three=>3}
# Using Binding#local_variables (Ruby 2.2+)
def bar(one: 1, two: 2, three: 3)
binding.local_variables.params.map { |p|
[p, binding.local_variable_get(p)]
}.to_h
end
#=> {:one=>1, :two=>2, :three=>3}