使用带有默认值的选项哈希作为ruby中的参数是一种很好的干净方法

Pet*_*son 8 ruby hash

假设我想要一个像这样调用的方法:

 tiger = create_tiger( :num_stripes => 12, :max_speed => 43.2 )
 tiger.num_stripes # will be 12
Run Code Online (Sandbox Code Playgroud)

其中一些选项具有默认值:

 tiger = create_tiger( :max_speed => 43.2 )
 tiger.num_stripes # will have some default value
Run Code Online (Sandbox Code Playgroud)

在方法实现中实现默认行为的一种很好的惯用ruby方法是什么?

Ste*_*sen 21

def foo(options = {})
  options = { ... defaults ... }.merge(options)
end
Run Code Online (Sandbox Code Playgroud)


Top*_*gio 18

如果您使用的是Rails(不仅仅是纯Ruby),那么稍微简短的方法就是

def foo(options = {})
  options.reverse_merge! { ... defaults ... }
end
Run Code Online (Sandbox Code Playgroud)

这样做的另一个好处是可以让你更干净地做多行:

def foo(options = {})
  options.reverse_merge!(
    :some_default => true,
    :other_default => 5
  )
end
Run Code Online (Sandbox Code Playgroud)


tad*_*man 6

通常最好将安全默认值封装在声明为常量的哈希中.例如:

要求'ostruct'

require 'ostruct'

class Tiger < OpenStruct
  DEFAULTS = {
    :num_stripes => 12,
    :max_speed => 43.2
  }.freeze

  def initialize(options = { })
    super(DEFAULTS.merge(options))
  end
end

tiger = Tiger.new(:max_speed => 19.95)

puts tiger.max_speed
puts tiger.num_stripes
Run Code Online (Sandbox Code Playgroud)

重要的是要注意,当合并Hash对象时,String和Symbol键是不同的,并且不会像您期望的那样组合.在Rails环境中,您始终可以使用Hash#symbolize_keys将其转换为另一个,或者将它们声明为HashWithIndifferentAccess,它会为您绘制差异.


bwe*_*t87 6

如果有人从谷歌看到这个,这个问题已经过时了。现代且更简洁的答案(使用 Ruby > 2.0)是使用关键字参数。它们有几个优点。

1.) 您可以要求哈希中的键名。(在红宝石> 2.1)

2.) 您不必在函数中“解包”散列。密钥只是作为变量传递给您。(因此你不必这样做speed = opts[:speed]

3.) 更干净

def foo(num_stripes: 12, **rest)
  print num_stripes, rest
end

foo({max_speed: 42}) # would print '12, {max_speed: 42}'
Run Code Online (Sandbox Code Playgroud)

在此处查看完整的 ruby​​ 文档:http : //www.ruby-doc.org/core-2.1.0/doc/syntax/methods_rdoc.html#label-Array%2FHash+Argument

还有一篇不错的小博文:http : //robots.thoughtbot.com/ruby-2-keyword-arguments