【问题标题】:Making an option false by default默认情况下将选项设为 false
【发布时间】:2012-08-09 23:36:13
【问题描述】:

这是在 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 有这方面的模式吗? (最小更好——我不需要完整的命令行选项解析器。)

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

【问题讨论】:

    标签: ruby options


    【解决方案1】:

    一个简单的方法是使用 Hash#fetch 的第二个参数

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

    对于复杂的默认值,fetch 也可以获取一个块,如果值不在散列中,则执行该块。见:http://ruby-doc.org/core-1.9.3/Hash.html#method-i-fetch

    【讨论】:

    • 非常好!我可能以前见过这个,但我不记得了。谢谢!
    【解决方案2】:

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

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

    这样您的所有选项都设置在一个地方,您只需合并用户提供的选项。

    【讨论】:

    • 我喜欢从默认值开始并在用户提供的选项中合并的想法,但是你在@options 的范围内遇到了一个错误!观看您的self。 :)
    • 哦,抱歉,这并不是一个完整的解决方案 :) 我将对其进行编辑并将其放入...
    【解决方案3】:
    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
    

    这不仅对于一个选项更简洁,而且如果您有更多选项,它会变得更好。此外,它对truefalse 使用相同的模式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-16
      • 1970-01-01
      • 2016-04-15
      • 2014-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-03
      相关资源
      最近更新 更多