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

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

tiger = create_tiger( :num_stripes => 12, :max_speed => 43.2 ) tiger.num_stripes # will be 12 

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

  tiger = create_tiger( :max_speed => 43.2 ) tiger.num_stripes # will have some default value 

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

如果您使用的是Rails(不仅仅是普通的Ruby),那么稍微短一些的方法就是

 def foo(options = {}) options.reverse_merge! { ... defaults ... } end 

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

 def foo(options = {}) options.reverse_merge!( :some_default => true, :other_default => 5 ) end 
 def foo(options = {}) options = { ... defaults ... }.merge(options) end 

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

要求’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 

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

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

1.)您可以在散列中要求密钥的名称。 (在ruby中> 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}' 

请参阅完整的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