红宝石 - 关键参数 - 你可以把所有的关键字参数作为一个哈希?怎么样? [英] Ruby - Keyword Arguments - Can you treat all of the keyword arguments as a hash? How?

查看:197
本文介绍了红宝石 - 关键参数 - 你可以把所有的关键字参数作为一个哈希?怎么样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个看起来像这样的方法:

I have a method that looks like this:

def method(:name => nil, :color => nil, shoe_size => nil) 
  SomeOtherObject.some_other_method(THE HASH THAT THOSE KEYWORD ARGUMENTS WOULD MAKE)
end

有关任何给定的呼叫,我可以接受可选值的任意组合。我喜欢的命名参数,因为我只看了方法的签名,看看有什么可用的选项。

For any given call, I can accept any combination of optional values. I like the named arguments, because I can just look at the method's signature to see what options are available.

我不知道是否有什么我都以大写字母code样品在上述一个快捷方式是。

What I don't know is if there is a shortcut for what I have described in capital letters in the code sample above.

早在昔日,它使用的是:

Back in the olden days, it used to be:

def method(opts)
  SomeOtherObject.some_other_method(opts)
end

优雅,简单,几乎欺骗。

Elegant, simple, almost cheating.

有那些关键参数的快捷方式或做我必须重建我的选择哈希方法调用?

Is there a shortcut for those Keyword Arguments or do I have to reconstitute my options hash in the method call?

推荐答案

是的,这的的可能,但它不是很优雅。

Yes, this is possible, but it's not very elegant.

您将不得不使用参数方法,该返回方法的参数及其类型的数组(在这种情况下,我们只有关键字参数)。

You'll have to use the parameters method, which returns an array of the method's parameters and their types (in this case we only have keyword arguments).

def foo(one: 1, two: 2, three: 3)
  method(__method__).parameters
end  
#=> [[:key, :one], [:key, :two], [:key, :three]]

知道了,有各种方法如何使用该阵列来获得所有的参数及其提供的值的哈希值。

Knowing that, there's various ways how to use that array to get a hash of all the parameters and their provided values.

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}

# Or another way
def foo(one: 1, two: 2, three: 3)
  params = method(__method__).parameters.map(&:last)
  opts = Hash[ params.map { |p| [p, eval(p.to_s)] } ]
end  
#=> {:one=>1, :two=>2, :three=>3}

所以,你的例子看起来像

So your example would look like

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

仔细想想用这个。这是聪明的,但在可读性为代价,别人读你的code不会喜欢它。

Think carefully about using this. It's clever but at the cost of readability, others reading your code won't like it.

您可以把它稍微有一个辅助方法读取。

You can make it slightly more readable with a helper method.

# Returns the parameters of the caller.
def params
  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

更新:推出红宝石2.2 绑定#local_variables 可以用来代替#方法的参数。要小心,因为你必须定义方法中的任何额外的局部变量之前调用 local_variables

Update: Ruby 2.2 introduced Binding#local_variables which can be used instead of Method#parameters. Be careful because you have to call local_variables before defining any additional local variables inside the method.

# 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 Bingind#local_variables
def bar(one: 1, two: 2, three: 3)
  params = binding.local_variables
  opts = params.map { |p| [p, eval(p.to_s)] }.to_h
end
#=> {:one=>1, :two=>2, :three=>3}

这篇关于红宝石 - 关键参数 - 你可以把所有的关键字参数作为一个哈希?怎么样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆