32

有人会解释选项哈希吗?我正在学习 testfirst.org 的 ruby​​ 课程。练习 10 (temperature_object) 需要了解选项哈希。

4

5 回答 5

55

选项哈希是一个很好的概念,由 ruby​​ 解析器的一个特性启用。比如说,您有一个带有一些必需参数的方法。您也可以传递一些可选参数。随着时间的推移,您可能会添加更多可选参数或删除旧参数。为了保持方法声明的干净和稳定,您可以在哈希中传递所有这些可选参数。这种方法看起来像这样:

def foo(arg1, arg2, opts = {})
  opts.to_s # just return a string value of opts
end

所以它有两个必需的值和最后一个参数,默认值为哈希。如果你没有任何可选参数要传递,你可以这样称呼它:

foo(1, 2) # => "{}"

如果你确实有一些可选的东西,你可以这样称呼它:

foo(1, 2, {truncate: true, redirect_to: '/'}) # => "{:truncate=>true, :redirect_to=>\"/\"}"

这段代码对 ruby​​ 来说非常地道,以至于它的解析器实际上允许您在将 hash 作为最后一个参数传递给方法时省略花括号:

foo(1, 2, truncate: true, redirect_to: '/') # => "{:truncate=>true, :redirect_to=>\"/\"}"

例如,如果您使用 rails,您会在各处看到选项散列。在这里,我在我的应用程序中只打开了一个随机控制器:

class ProductsController < ApplicationController
  before_filter :prepare_search_params, only: :index
                                    #    ^^^^^^^^^^ options hash here

因此,简而言之:options hash 是位于最后且具有默认值的方法的参数{}。您通常会将哈希传递给它(因此得名)。

于 2013-08-23T16:34:54.523 回答
12

当需要将可选参数传递给方法时,会经常使用选项哈希。

例如,如果方法有一两个可选参数,你可以写

def method(arg1, arg2 = nil, arg3 = nil)
  ...
end

但是,如果您有更多可选参数,那么每次都将它们分配为 nil 会变得很难看。这是允许您编写的选项哈希

def method(arg1, options={})
  @arg1 = arg1
  @arg2 = options[:arg2]
  ....
  @arg15 = options[:arg15]
end
于 2014-12-24T14:28:22.293 回答
7

{}选项散列是指使用散列 ( )将选项传递给方法的约定,如下所示

my_func(arg1, arg2, {:opt1 => 'foo', :opt2 => 'bar'})

约定是将选项散列作为最后一个参数,以便可以将其设为可选。例如

def my_func(argument1, argument2, options = {})
   ...
end

所以选项哈希没有什么特别的。它只是一个可选的最终参数,它是一个哈希。选项散列非常方便和常见,解释器还可以让你去掉大括号(这是关于它们的一个“特殊”部分)

my_func(arg1, arg2, :opt1 => 'foo', :opt2 => 'bar')

结合 Ruby 的 Symbol 哈希键快捷键和可选的括号,这看起来非常干净:

my_func arg1, arg2, opt1: 'foo', opt2: 'bar'
于 2013-08-23T16:57:35.597 回答
7

由于所有这些答案都是正确的,ruby 2 改进了对关键字参数的支持。

您可以使用默认哈希参数将您的方法定义为*args,并去掉options = {}.

def foo(bar: 'initial')
  puts bar
end

foo # => 'initial'
foo(bar: 'final') # => 'final'

必需的参数:你需要在键后加一个冒号(你也需要 ruby​​ 2.1)

def foo(bar:)
  puts bar
end

foo # => ArgumentError: missing keyword: bar
foo(bar: 'baz') # => 'baz'   

可选参数,您可以将默认设置为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

您也可以将标准位置参数与这个新的散列参数表示法一起使用。您将在此博客官方文档中找到更多信息。

奖励:重构很容易,因为您可以在不更改方法调用的情况下摆脱方法的选项哈希。但是......这并不完全正确,如果您有一个带有意外选项的电话,您将获得一个ArgumentError: unknown keyword: invalid_arg.

于 2015-08-30T01:51:05.007 回答
4

反向合并是在 ruby​​/rails 中实现选项哈希的最佳方式:

def set_state_application(options_hash)
  options_hash.reverse_merge!(send_email: true, other_default_val: 'a') #will set defaults
  self.update_column(:status_id, VendorEnums::VendorStatus::APPLICATION)
  VendorMailer.email_application(self) if options_hash[:send_email]
  save_state
end
于 2014-03-20T01:40:00.297 回答