【问题标题】:Ruby: Most concise way to use an ENV variable if it exists, otherwise use default valueRuby:使用 ENV 变量(如果存在)的最简洁方法,否则使用默认值
【发布时间】:2011-12-01 17:58:13
【问题描述】:

在 Ruby 中,我正在尝试编写一个使用已设置变量的行,否则默认为某个值:

myvar = # assign it to ENV['MY_VAR'], otherwise assign it to 'foobar'

我可以这样写代码:

if ENV['MY_VAR'].is_set? #whatever the function is to check if has been set
  myvar = ENV['MY_VAR']
else
  myvar = 'foobar'
end

但这相当冗长,我正在尝试以最简洁的方式编写它。我该怎么做?

【问题讨论】:

  • 对于非 ENV 变量,在未设置时不会很好地失败,您需要使用类似 defined?( some_variable ) ? some_variable : "default value"

标签: ruby hash


【解决方案1】:
myvar = ENV['MY_VAR'] || 'foobar'

注意这有点不正确(如果哈希可以包含值 nil),但由于 ENV 只包含字符串,它可能就足够了。

【讨论】:

  • 这如何处理空字符串,"" 例如,如果我将我的 ENV 变量设置为 MY_VAR= rails smyvar 是否会设置为 "" 或会设置为"foobar"吗?
  • 答案: 它将被设置为一个空字符串,""。根据您的目标,这可能是您想要的结果。如果没有,你也可以使用ENV.key?( "MY_VAR" )来查看变量是否设置了?
【解决方案2】:

一般Hash最可靠的方法是询问是否有key:

myvar = h.has_key?('MY_VAR') ? h['MY_VAR'] : 'default'

如果您不关心 nilfalse 值(即您希望将它们视为“不存在”),那么 undur_gongor 的方法很好(当 hENV):

myvar = h['MY_VAR'] || 'foobar'

如果您想允许nil 出现在您的哈希中但假装它不存在(即nil 值与“不存在”相同)同时允许false 在您的哈希中:

myvar = h['MY_VAR'].nil? ? 'foobar' : h['MY_VAR']

最终,这实际上取决于您的确切意图,您应该选择与您的意图相匹配的方法。 if/else/end? : 之间的选择当然是一个品味问题,“简洁”并不意味着“最少的字符数”,所以可以随意使用三元或 if 块。

【讨论】:

  • 同上@undur_gongor。感谢您的彻底!
  • 对于上面代码中的h - 这只是hash 的临时值还是我们应该将h 与我们的代码/名称中的某些内容相关联?
  • @CanuckT h 是一个通用散列,可以是任何散列。我想我使用了h 而不是ENV,因为ENV 或它的行为方式没有什么特别的,它只是关于哈希。
【解决方案3】:
hash.fetch(key) { default_value }

如果存在则返回值,如果键不存在则返回default_value

【讨论】:

  • hash.fetch(key, default_value),如果默认值不依赖于密钥。
  • @mu 太短:是的。通常我在做hash.fetch(key) { raise "#{key.inspect} doesn't exist!" },所以当有两个参数时,我不能 100% 确定正确的顺序。
  • 我(好像几乎所有其他人一样)倾向于忘记 fetch 甚至存在,所以 +1 用于使用整个 API。
  • @muistooshort:为什么大多数人不使用它?是因为太长,还是教程没教?
  • 可能和没有人使用Array#at的原因相同:他们不知道,教程没有涵盖它,他们认为“简洁”意味着“短”,他们认为一堆符号比方法调用等更 Rubyish。尽管许多程序员喜欢认为他们有个人主义倾向,但程序员和其他任何人一样都是群体思维和习惯的受害者。但现在我们想进入programmers.stackexchange.com 领域并冒着异端的风险。
【解决方案4】:

这对我最有效:

ENV.fetch('VAR_NAME',"5445")

【讨论】:

【解决方案5】:

虽然它与您给出的具体示例无关,因为您实际上是在询问哈希键,而不是变量,但 Ruby 确实提供了一种检查变量定义的方法。使用 defined? 关键字(它不是一个方法,而是一个关键字,因为它需要解释器的特殊处理),如下所示:

a = 1
defined? a
  #=> "local-variable"

@a = 2
defined? @a
  #=> "instance-variable"

@@a = 3
defined? @@a
  #=> "class-variable"

defined? blahblahblah
  #=> nil

因此你可以这样做:

var = defined?(var) ? var : "default value here"

据我所知,这是除了丑陋的begin/rescue/end 块之外的唯一方法,可以按照您要求的方式定义变量,而不会冒 NameError 的风险。正如我所说,这不适用于哈希,因为:

hash = {?a => 2, ?b => 3}
defined? hash[?c]
  #=> "method"

即您正在检查方法 [] 是否已定义,而不是您使用它来访问的键/值对。

【讨论】:

    【解决方案6】:
    myvar = ENV.fetch('MY_VAR') { 'foobar' }
    

    如果ENV['MY_VAR'] 未设置,则'foobar' 是默认值。

    【讨论】:

      【解决方案7】:

      另一种可能的替代方法,即使 ENV['MY_VAR'] 结果是错误值也可以使用

      myvar  = ENV['MY_VAR'].presence || 'foobar'
      

      【讨论】:

        【解决方案8】:

        我写的Demand gem 让它变得非常简洁和干燥:

        myvar = demand(ENV['MY_VAR'], 'foobar')
        

        只有当它存在时才会使用ENV['MY_VAR']。也就是说,只要它是 nil、空或只有空格的字符串,它就会丢弃它,而是提供默认值。

        如果ENV['MY_VAR'] 的有效值是假的(例如false),或者无效值是真值(例如""),则使用|| 之类的解决方案将不起作用。

        【讨论】:

          【解决方案9】:

          我是 Ruby 的新手,发布我在 2021 年找到的答案,可能对某人有用。

          检查 env 键是否存在:

           include?(name) → true or false
           has_key?(name) → true or false
           member?(name) → true or false
           key?(name) → true or false
          

          使用默认值获取环境:

           ENV.fetch(name, :default_val)
          

          参考:https://docs.ruby-lang.org/en/master/ENV.html

          【讨论】:

            【解决方案10】:

            myvar = ENV['MY_VAR'].is_set? ? ENV['MY_VAR'] : 'foobar'

            这样你就保留了 .is_set?方法。

            【讨论】:

            • is_set? 是 ruby​​ 方法吗?我以为是我编造的,因为我不知道我所要求的方法的名称。
            • 至少在我的 ruby​​ 版本中没有 is_set?,有一个 ENV.has_key?
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2022-11-14
            • 2014-08-07
            • 1970-01-01
            • 2021-11-18
            • 2016-05-08
            • 1970-01-01
            • 2012-02-09
            相关资源
            最近更新 更多