5

这是在 Ruby 中设置默认值的常用方法:

class QuietByDefault
  def initialize(opts = {})
    @verbose = opts[:verbose]
  end
end

这是一个容易掉入的陷阱:

class VerboseNoMatterWhat
  def initialize(opts = {})
    @verbose = opts[:verbose] || true
  end
end

这是一个正确的方法:

class VerboseByDefault
  def initialize(opts = {})
    @verbose = opts.include?(:verbose) ? opts[:verbose] : true
  end
end

最好/最干净的编码方式是VerboseByDefault什么?(当然,我可以把它排除在外。)

一般在 Ruby 代码中广泛使用什么模式(如果有的话)?ActiveSupport 有这方面的模式吗?(最小更好——我不需要完整的命令行选项解析器。)

咆哮 PS:我不喜欢处理默认选项true的代码与处理默认false选项的代码之间的不对称。一种在两者之间进行更改而不引起错误的模式将是一件好事。

4

3 回答 3

7

A simple way to do it is by using the second argument to Hash#fetch

class VerboseByDefault
  def initialize(opts = {})
    @verbose = opts.fetch(:verbose, true)
  end
end

For complex defaults, fetch can also take a block, which is executed if the value isn't in the hash. See: http://ruby-doc.org/core-1.9.3/Hash.html#method-i-fetch

于 2012-08-14T02:00:03.413 回答
1

我通常将其视为设置所有默认值,然后将它们与 opts 合并。如..

def initialize(opts = {})
  @options = { :verbose => false, :foo => 42 } 
  @options.merge!(opts)
  # ...
end

This way all of your options are set in one place and you just merge the user supplied ones.

于 2012-08-13T17:47:05.767 回答
0
require 'active_support/core_ext/hash/reverse_merge'
class VerboseByDefault
  DEFAULTS = { verbose: true }
  def initialize(opts = {})
    opts.reverse_merge!(DEFAULTS)
    @verbose = opts[:verbose]
  end
end

This isn't only a little cleaner just for one option, but it becomes way better if you have more options. Also, it uses the same pattern for true and false.

于 2012-08-14T01:16:54.357 回答