web-dev-qa-db-fra.com

Comment utiliser Array # Dig et Hash # Dig introduits dans Ruby 2.3?

Ruby 2.3 introduit une nouvelle méthode sur Array et Hash appelée Dig. Les exemples que j'ai vus dans les articles de blog concernant la nouvelle version sont artificiels et compliqués:

# 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

Je n'utilise pas de tableaux plats à triple imbriqué. Quel est un exemple réaliste de la façon dont cela serait utile?

METTRE À JOUR

Il s'avère que ces méthodes résolvent l'une des questions les plus fréquemment posées par Ruby. Les questions ci-dessous ont quelque chose comme 20 doublons, qui sont tous résolus en utilisant Dig:

Comment éviter NoMethodError pour les éléments manquants dans les hachages imbriqués, sans vérifications nulles répétées?

Ruby Style: Comment vérifier si un élément de hachage imbriqué existe

31
user513951

Dans notre cas, NoMethodErrors en raison de nil références sont de loin les erreurs les plus courantes observées dans nos environnements de production.

Le nouveau Hash#Dig vous permet d'omettre les contrôles nil lors de l'accès à des éléments imbriqués. Étant donné que les hachages sont mieux utilisés lorsque la structure des données est inconnue, ou volatile, le support officiel pour cela a beaucoup de sens. 

Prenons votre exemple. Le suivant:

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

Est-ce que not est équivalent à:

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

Dans le cas où user[:user] ou user[:user][:address] est nil, cela entraînerait une erreur d'exécution.

Au contraire, cela équivaut à ce qui suit, qui est l'idiome actuel:

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

Notez qu'il est trivial de passer une liste de symboles créée ailleurs dans Hash#Dig, alors qu'il n'est pas très simple de recréer cette dernière construction à partir d'une telle liste. Hash#Dig vous permet d’effectuer facilement un accès dynamique sans vous soucier des références nil.

Clairement, Hash#Dig est également beaucoup plus court.


Un point important à noter est que Hash#Dig renvoie lui-même nil si l'une des clés s'avère être, ce qui peut entraîner la même classe d'erreurs une étape sur la ligne, il peut donc être judicieux de fournir une valeur par défaut raisonnable. . (Cette façon de fournir un objet qui répond toujours aux méthodes attendues s'appelle le Modèle d'objet nul .)

Encore une fois, dans votre exemple, une chaîne vide ou quelque chose comme "N/A", selon ce qui a du sens:

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

L’une des méthodes possibles est que l’opérateur Splat lit un modèle de document inconnu.

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

C'est utile pour vous frayer un chemin à travers des tableaux de hachage/tableaux profondément imbriqués, ce qui pourrait être ce que vous obtiendriez d'un appel d'API, par exemple.

En théorie, il enregistre une tonne de code qui, sinon, vérifierait à chaque niveau s'il existe un autre niveau sans lequel vous risquez des erreurs constantes. En pratique, vous aurez peut-être encore besoin de beaucoup de ce code, car Dig créera encore des erreurs dans certains cas (par exemple, si quelque chose dans la chaîne est un objet sans clé.)

C'est pour cette raison que votre question est réellement valable - Dig n'a pas vu l'utilisation à laquelle nous pourrions nous attendre. Ceci est commenté ici par exemple: Pourquoi personne ne parle de Dig .

Pour que Dig évite ces erreurs, essayez le KeyDial gem, que j'ai écrit pour boucler Dig et le forcer à renvoyer nil/default si une erreur survient.

0
Convincible