【问题标题】:Safe navigation equivalent to Rails try for hashes等效于 Rails 的安全导航 try for hashes
【发布时间】:2016-06-25 16:02:35
【问题描述】:

在 Rails 中,您可以使用 hash.try(:[], :key),如果 hash 可能是 nil,这会有所帮助。 是否有使用新的 Ruby 2.3 安全导航运算符 &.[] 的等效版本?

【问题讨论】:

标签: ruby-on-rails ruby


【解决方案1】:

&. 不等同于 Rails 的 try,但您可以使用 &. 来表示哈希。随便用,没什么特别的。

hash[:key1]&.[](:key2)&.[](:key3)

虽然我不会那样做。

【讨论】:

  • 很好,&.try 不同。我只考虑hashnil 的情况。我最终使用的是hash&.[](:key)
  • @bbozo 是的。 &. 是在 Ruby 2.3 中引入的。
  • hash&.dig(:key1, :key2, :key3) 看起来更好:)
【解决方案2】:

Ruby 2.3 及更高版本

现在有 Hash#dig 方法可以做到这一点:

重复检索每个键对象对应的值对象。

h = { foo: {bar: {baz: 1}}}

h.dig(:foo, :bar, :baz)           #=> 1
h.dig(:foo, :zot)                 #=> nil

http://ruby-doc.org/core-2.3.0_preview1/Hash.html#method-i-dig

Ruby 2.3 前

我通常在初始化器中放入类似的东西:

Class Hash
    def deep_fetch *args
      x = self
      args.each do |arg|
        x = x[arg]
        return nil if x.nil?
      end
      x
    end
end

然后

response.deep_fetch 'PaReqCreationResponse', 'ThreeDSecureVERes', 'Message', 'VERes', 'CH', 'enrolled'

在一个古怪的情况下。

社区的普遍共识似乎是避免尝试和孤独的运营商&.

【讨论】:

  • 在用例中看起来与 dig 非常相似,在 2.3 中引入,就像 &.。有什么不同吗?
  • 最好将Hash 的扩展和prepend 放在一个模块中,而不是直接进行monkeypatch。
  • @DavidS。能详细点吗?
  • 将您的扩展放在一个模块中,您可以将它们与您正在修补的实际类隔离开来进行测试,然后通过Module#prepend 实际修补它将使您能够从以下位置调用super你的猴子补丁来调用你正在覆盖的方法。
  • 但是h.dig(:foo, :bar, :baz, :bing) 会报错
【解决方案3】:

虽然hash&.[](:key) 对训练有素的 ruby​​ 专家来说很优雅,但我只使用 hash && hash[:key] 因为它对我之后的程序员来说更好更直观,他们可能不熟悉 ruby​​ 的复杂性。代码库中的一些额外字符有时可以为其他人节省大量的谷歌搜索。

(当然,鉴于您要在其中使用它的上下文是在条件语句中。)

【讨论】:

  • ...尤其是这种语法 (&.[](:key)) 根本无法搜索!另一方面,dig 可以通过使用方式识别为方法;因此,通过搜索ruby method dig,例如,相对容易获得更多信息
【解决方案4】:

使用安全导航运算符比使用hash&.[](:slug) 更清晰的方法是使用fetch 方法:

hash&.fetch(:slug)

如果您的键可能没有定义,您可以使用第二个参数作为默认值:

hash&.fetch(:slug, nil)

【讨论】:

  • 这在某些场景下可能是合适的,但是#[]和#fetch不是同一个方法没有任何价值,如果哈希中不存在key,fetch会抛出异常。
  • @ZoFreX:这就是为什么我在答案中包含fetch(…, nil),这与#[]完全相同。
【解决方案5】:

hash 为 nil 时,接受的答案将不予考虑...

您可以在.try 之前使用安全导航运算符重写您拥有的内容,这将起作用

hash&.try(:[], :key)

但你也可以使用:

http://ruby-doc.org/core-2.3.0_preview1/Hash.html#method-i-dig

在哈希上执行此操作的一种方法是...

hash&.dig(:key1, :key2 ...)

如果不存在任何键提取,则返回 nil。

{ key1: { key2: 'info' } } 

将返回“信息”

{ key1: { wrong_key: 'info' } } 

会返回nil

【讨论】:

  • 这是干净利落的方法。 hash&.dig( :key1 )。谢谢。
猜你喜欢
  • 2011-04-15
  • 2013-10-17
  • 1970-01-01
  • 2018-02-24
  • 1970-01-01
  • 2019-07-23
  • 1970-01-01
  • 1970-01-01
  • 2011-01-23
相关资源
最近更新 更多