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
:
Ruby Style: Comment vérifier si un élément de hachage imbriqué existe
Dans notre cas, NoMethodError
s 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) || ""
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
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.