web-dev-qa-db-ja.com

Ruby 2.3で導入されたArray#DigとHash#Digを使用するにはどうすればよいですか?

Ruby 2.3では、ArrayおよびHashDigと呼ばれる新しいメソッドが導入されました。新しいリリースについてのブログ投稿で見た例は、不自然で複雑です。

# 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

トリプルネストフラットアレイを使用していません。これがどのように役立つかの現実的な例は何ですか?

[〜#〜] update [〜#〜]

これらのメソッドは、最もよく尋ねられるRubyの質問の1つを解決します。以下の質問には、20個の重複のようなものがあり、すべてDigを使用して解決します:

繰り返しnilチェックせずに、ネストされたハッシュ内の欠落要素のNoMethodErrorを回避する方法?

Rubyスタイル:ネストされたハッシュ要素が存在するかどうかを確認する方法

34
user513951

この場合、NoMethodError参照によるnilsは、実稼働環境で見られる最も一般的なエラーです。

新しいHash#Digを使用すると、ネストされた要素にアクセスするときにnilチェックを省略できます。ハッシュはデータの構造が不明または不安定な場合に最もよく使用されるため、これを公式にサポートすることは非常に理にかなっています。

例を見てみましょう。以下:

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

Isnotと同等:

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もずっと短いです。


注意すべき重要な点の1つは、いずれかのキーが判明した場合、Hash#Dig自体がnilを返すことです。賢明なデフォルトを提供することをお勧めします。 (期待されるメソッドに常に応答するオブジェクトを提供するこの方法は、 Null Object Pattern と呼ばれます。)

繰り返しますが、あなたの例では、空の文字列または「N/A」のようなものが、意味に応じて異なります。

user.Dig(:user, :address, :street1) || ""
62
Drenmi

1つの方法は、スプラット演算子を使用して、未知のドキュメントモデルから読み取ることです。

some_json = JSON.parse( '{"people": {"me": 6, ... } ...}' )
# => "{"people" => {"me" => 6, ... }, ... }
a_bunch_of_args = response.data[:query]
# => ["people", "me"]
some_json.Dig(*a_bunch_of_args)
# => 6
9
acsmith

深くネストされたハッシュ/配列を使用して作業する場合に役立ちます。これは、たとえば、API呼び出しから返される場合があります。

理論上、別のレベルが存在するかどうかを各レベルでチェックする大量のコードを保存します。 practiseでは、Digがエラーを作成する場合があるため、このコードの多くが必要になる場合があります(たとえば、チェーン内の何かがキーなしオブジェクト。)

あなたの質問が実際に本当に有効であるのはこのためです-Digは私たちが期待するかもしれない使用法を見ていません。これは、たとえばここでコメントされています: なぜDigについて誰も話さない

Digでこれらのエラーを回避するには、 KeyDial gemを試してください。これはDigをラップして、エラーが発生した場合にnil/defaultを返すように強制します。

1
Convincible