Ruby 2.3在ArrayHash上引入了一个名为dig的新方法.我在博客文章中看到的关于新版本的例子都是精心设计和复杂的:

# Hash#dig
user = {
  user: {
    address: {
      street1: '123 Main street'
    }
  }
}

user.dig(:user, :address, :street1) # => '123 Main street'

# Array#dig
results = [[[1, 2, 3]]]
results.dig(0, 0, 0) # => 1

我没有使用三层嵌套平面array.什么是一个现实的例子,说明这将是多么有用?

UPDATE

事实证明,这些方法解决了最常见的Ruby问题之一.下面的问题大约有20个副本,所有问题都可以用dig个来解决:

How to avoid NoMethodError for missing elements in nested hashes, without repeated nil checks?

Ruby Style: How to check whether a nested hash element exists

推荐答案

在我们的例子中,nil个引用导致的NoMethodError个错误是我们在生产环境中看到的最常见的错误.

新的Hash#dig允许您在访问嵌套元素时省略nil个判断.由于哈希最适合用于数据 struct 未知或不稳定的情况,因此获得官方支持非常有意义.

让我们以你为例.以下是:

user.dig(:user, :address, :street1)

not等于:

user[:user][:address][:street1]

user[:user]user[:user][:address]nil的情况下,这将导致运行时错误.

相反,它相当于当前的习语:

user[:user] && user[:user][:address] && user[:user][:address][:street1]

请注意,将在其他地方创建的符号列表传递到Hash#dig中是很简单的,而从这样的列表中重新创建后一种构造则不是很简单.Hash#dig允许您轻松进行动态访问,而无需担心nil个引用.

显然,Hash#dig也要短得多.


需要注意的一个重要点是,如果任何一个键被证明是,Hash#dig本身会返回nil,这可能会导致同一类错误,因此最好提供一个合理的默认值.(这种提供始终响应预期方法的对象的方式称为Null Object Pattern.)

同样,在你的例子中,一个空字符串或类似"N/A"的东西,取决于什么是合理的:

user.dig(:user, :address, :street1) || ""

Ruby相关问答推荐

鲁比.METHOD_MISSING+SEND对于带有命名参数的混合参数失败

如何在 Ruby 中正确编写代码?以便它产生正确的输出?

字符串长度多显示一个字符 - ruby

ruby:rubocop 抱怨将 if else 转换为 case 语句

有人可以解释 Ruby 在块中使用管道字符吗?

ruby 是否支持 case 语句中的范围?

Ruby:从字节创建一个字符串

Ruby 输出 Unicode 字符

Ruby字符串上的扫描和匹配有什么区别

需要必要的库和/或头文件时如何安装 ruby​​-debug

`respond_to?` 与 `respond_to_missing?`

在不同的换行符上拆分

在 OSX 10.10 Yosemite 上安装 Nokogiri

如何获取当前 rake 任务的 PID?

rbenv、rvm 和 chruby 有什么区别?

何时在 Ruby 中使用 `require`、`load` 或 `autoload`?

Python 中的一切都像 Ruby 一样是对象吗?

Ruby 中的Monkey Patching到底是什么意思?

在 Ruby 中使用元组?

Ruby:是否可以在模块中定义类方法?