Ser*_*sev 49
Options hash是一个很好的概念,由ruby解析器的一个特性启用.比如说,你有一个带有一些必需参数的方法.您也可以传递一些可选参数.随着时间的推移,您可以添加更多可选参数或删除旧参数.要使方法声明保持干净和稳定,您可以在哈希中传递所有这些可选参数.这样的方法看起来像这样:
def foo(arg1, arg2, opts = {})
opts.to_s # just return a string value of opts
end
Run Code Online (Sandbox Code Playgroud)
所以它有两个必需值和最后一个参数,默认值为hash.如果您没有要传递的任何可选参数,请将其称为:
foo(1, 2) # => "{}"
Run Code Online (Sandbox Code Playgroud)
如果你有可选的东西,你可以这样称呼它:
foo(1, 2, {truncate: true, redirect_to: '/'}) # => "{:truncate=>true, :redirect_to=>\"/\"}"
Run Code Online (Sandbox Code Playgroud)
这个代码对于ruby来说是非常惯用的,它的解析器实际上允许你在将hash作为方法的最后一个参数传递时省略花括号:
foo(1, 2, truncate: true, redirect_to: '/') # => "{:truncate=>true, :redirect_to=>\"/\"}"
Run Code Online (Sandbox Code Playgroud)
例如,如果你使用rails,你会看到各处的选项哈希值.在这里,我在我的应用程序中打开了一个随机控制器:
class ProductsController < ApplicationController
before_filter :prepare_search_params, only: :index
# ^^^^^^^^^^ options hash here
Run Code Online (Sandbox Code Playgroud)
所以,简而言之:options hash是一个方法的参数,它位于最后,默认值为{}.你通常会把哈希传给它(因此得名).
当需要将可选参数传递给方法时,会大量使用选项哈希.
例如,如果method有两个可选的args,你可以编写
def method(arg1, arg2 = nil, arg3 = nil)
...
end
Run Code Online (Sandbox Code Playgroud)
但是如果你有更多可选的arg,那么每次将它们分配给nil都会变得很难看.这里有选项哈希,允许你写
def method(arg1, options={})
@arg1 = arg1
@arg2 = options[:arg2]
....
@arg15 = options[:arg15]
end
Run Code Online (Sandbox Code Playgroud)
选项哈希是指使用hash({})将选项传递给方法的约定
my_func(arg1, arg2, {:opt1 => 'foo', :opt2 => 'bar'})
Run Code Online (Sandbox Code Playgroud)
惯例是将选项哈希作为最后一个参数,以便可以将其设置为可选.例如
def my_func(argument1, argument2, options = {})
...
end
Run Code Online (Sandbox Code Playgroud)
所以选项哈希并不特别.它只是一个可选的最后一个参数,它是一个哈希.选项哈希非常方便和通用,翻译也可以让你不用括号(这是关于它们的"特殊"部分)
my_func(arg1, arg2, :opt1 => 'foo', :opt2 => 'bar')
Run Code Online (Sandbox Code Playgroud)
结合Ruby的Symbol哈希键快捷键和可选括号,这可以看起来非常干净:
my_func arg1, arg2, opt1: 'foo', opt2: 'bar'
Run Code Online (Sandbox Code Playgroud)
由于所有这些答案都是正确的,因此ruby 2改进了对关键字参数的支持。
您可以使用默认的哈希参数as定义方法*args,然后删除options = {}。
def foo(bar: 'initial')
puts bar
end
foo # => 'initial'
foo(bar: 'final') # => 'final'
Run Code Online (Sandbox Code Playgroud)
必需参数:密钥后需要冒号(也需要ruby 2.1)
def foo(bar:)
puts bar
end
foo # => ArgumentError: missing keyword: bar
foo(bar: 'baz') # => 'baz'
Run Code Online (Sandbox Code Playgroud)
可选参数,您可以将默认设置为 nil
def foo(bar: nil, baz: 'aaa')
puts "#{bar}:#{baz}"
end
foo # => ':aaa'
foo(baz: 'zab') # => ':zab'
foo(bar: 'rab', baz: 'zab') # => 'rab:zab'
foo(bin: 'bin') # => ArgumentError: unknown keyword: bin
Run Code Online (Sandbox Code Playgroud)
您也可以将标准位置args与该新的哈希参数符号一起使用。您可以在此博客和官方文档中找到更多信息。
奖励:重构很容易,因为您可以摆脱方法的options哈希,而无需更改其调用。但是...这并非完全正确,如果您拨打带有意外选项的电话,则会收到ArgumentError: unknown keyword: invalid_arg。