Ruby 2.3 führt eine neue Methode für Array
und Hash
mit dem Namen Dig
ein. Die Beispiele, die ich in Blogeinträgen über die neue Version gesehen habe, sind erfunden und verschlungen:
# 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
Ich verwende keine dreifach verschachtelten flachen Arrays. Was ist ein realistisches Beispiel dafür, wie dies nützlich wäre?
UPDATE
Es stellt sich heraus, dass diese Methoden eine der am häufigsten gestellten Ruby-Fragen lösen. Die folgenden Fragen haben ungefähr 20 Duplikate, die alle mit Dig
gelöst werden:
Ruby Style: So prüfen Sie, ob ein verschachteltes Hash-Element vorhanden ist
In unserem Fall sind NoMethodError
s aufgrund von nil
-Referenzen bei weitem die häufigsten Fehler, die wir in unseren Produktionsumgebungen sehen.
Mit dem neuen Hash#Dig
können Sie beim Zugriff auf verschachtelte Elemente auf nil
-Prüfungen verzichten. Da Hashes am besten verwendet werden, wenn die Struktur der Daten unbekannt oder unbeständig ist, ist es sinnvoll, diese Unterstützung offiziell zu erhalten.
Nehmen wir ein Beispiel. Folgende:
user.Dig(:user, :address, :street1)
Ist nicht äquivalent zu:
user[:user][:address][:street1]
Wenn user[:user]
oder user[:user][:address]
nil
ist, führt dies zu einem Laufzeitfehler.
Es ist vielmehr gleichwertig mit der aktuellen Redewendung:
user[:user] && user[:user][:address] && user[:user][:address][:street1]
Beachten Sie, wie einfach es ist, eine Liste von Symbolen, die an anderer Stelle erstellt wurde, in Hash#Dig
zu übergeben, während das Erstellen des letzteren Konstrukts aus einer solchen Liste nicht einfach ist. Mit Hash#Dig
können Sie auf einfache Weise einen dynamischen Zugriff durchführen, ohne sich um nil
-Referenzen kümmern zu müssen.
Natürlich ist Hash#Dig
auch viel kürzer.
Ein wichtiger Punkt, der zu beachten ist, ist, dass Hash#Dig
selbst nil
zurückgibt, wenn sich herausstellt, dass sich einer der Schlüssel als derselbe auswirkt, was zu einer gleichen Fehlerkategorie führen kann. Daher kann es sinnvoll sein, einen sinnvollen Standardwert anzugeben . (Diese Art der Bereitstellung eines Objekts, das immer auf die erwarteten Methoden reagiert, wird als Nullobjektmuster bezeichnet.)
In Ihrem Beispiel wiederum eine leere Zeichenfolge oder etwas wie "N/A", je nachdem, was sinnvoll ist:
user.Dig(:user, :address, :street1) || ""
Eine Möglichkeit wäre, den Splat-Operator aus einem unbekannten Dokumentenmodell zu lesen.
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
Dies ist nützlich, wenn Sie sich durch tief verschachtelte Hashes/Arrays durcharbeiten möchten, die Sie beispielsweise von einem API-Aufruf erhalten würden.
In der Theorie wird eine Menge Code eingespart, der andernfalls auf jeder Ebene prüfen würde, ob eine andere Ebene vorhanden ist, ohne die Sie ständige Fehler riskieren. In der Praxis benötigen Sie möglicherweise noch eine Menge Code, da Dig
in einigen Fällen immer noch Fehler erzeugt (z. B. wenn etwas in der Kette ein Objekt ohne Schlüssel ist).
Aus diesem Grund ist Ihre Frage wirklich gültig - Dig
hat die erwartete Verwendung nicht erkannt. Dies wird zum Beispiel hier kommentiert: Warum niemand über Dig spricht.
Um Dig
diese Fehler zu vermeiden, versuchen Sie das KeyDial gem, das ich geschrieben habe, um Dig
zu wickeln, und erzwingen Sie, dass nil/default zurückgegeben wird, wenn ein Fehler auftritt.