Jes*_*mer 30 ruby hash arguments options keyword
我有一个看起来像这样的方法:
def method(:name => nil, :color => nil, shoe_size => nil)
SomeOtherObject.some_other_method(THE HASH THAT THOSE KEYWORD ARGUMENTS WOULD MAKE)
end
Run Code Online (Sandbox Code Playgroud)
对于任何给定的调用,我可以接受任意值的任意组合.我喜欢命名参数,因为我可以查看方法的签名以查看可用的选项.
我不知道的是,如果上面的代码示例中有大写字母描述的快捷方式.
回到过去,它曾经是:
def method(opts)
SomeOtherObject.some_other_method(opts)
end
Run Code Online (Sandbox Code Playgroud)
优雅,简单,几乎作弊.
这些关键字参数是否有快捷方式,还是我必须在方法调用中重构我的选项哈希?
Den*_*nis 19
是的,这是可能的,但它不是很优雅.
您将不得不使用该parameters方法,该方法返回方法的参数及其类型的数组(在这种情况下,我们只有关键字参数).
def foo(one: 1, two: 2, three: 3)
method(__method__).parameters
end
#=> [[:key, :one], [:key, :two], [:key, :three]]
Run Code Online (Sandbox Code Playgroud)
知道了,有多种方法可以使用该数组来获取所有参数及其提供值的哈希值.
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}
Run Code Online (Sandbox Code Playgroud)
所以你的例子看起来像
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
Run Code Online (Sandbox Code Playgroud)
仔细考虑使用它.它很聪明但是以可读性为代价,其他人阅读你的代码却不喜欢它.
您可以使用辅助方法使其更具可读性.
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
Run Code Online (Sandbox Code Playgroud)
更新:引入了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}
Run Code Online (Sandbox Code Playgroud)
当然!只需使用double splat(**)运算符即可.
def print_all(**keyword_arguments)
puts keyword_arguments
end
def mixed_signature(some: 'option', **rest)
puts some
puts rest
end
print_all example: 'double splat (**)', arbitrary: 'keyword arguments'
# {:example=>"double splat (**)", :arbitrary=>"keyword arguments"}
mixed_signature another: 'option'
# option
# {:another=>"option"}
Run Code Online (Sandbox Code Playgroud)
它就像常规的splat(*)一样,用于收集参数.您甚至可以将关键字参数转发给另一个方法.
def forward_all(*arguments, **keyword_arguments, &block)
SomeOtherObject.some_other_method *arguments,
**keyword_arguments,
&block
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6709 次 |
| 最近记录: |