La plus belle solution est une vieille réponse par Mladen Jablanović, car il vous permet de vous plonger dans la table de hachage plus profond que vous pouvez avec l'aide de direct, .try()
des appels, si vous voulez le code, toujours agréable à regarder:
class Hash
def get_deep(*fields)
fields.inject(self) {|acc,e| acc[e] if acc}
end
end
Vous devez être prudent avec divers objets (en particulier params
), parce que les Chaînes et les Tableaux aussi répondre à :[], mais la valeur retournée peut être pas ce que vous voulez, et le Tableau déclenche l'exception des Chaînes ou des Symboles utilisés comme indices.
C'est la raison pour laquelle, dans le modèle de formulaire de cette méthode (ci-dessous) le (généralement laid) de test pour .is_a?(Hash)
est utilisé à la place de (généralement mieux) .respond_to?(:[])
:
class Hash
def get_deep(*fields)
fields.inject(self) {|acc,e| acc[e] if acc.is_a?(Hash)}
end
end
a_hash = {:one => {:two => {:three => "asd"}, :arr => [1,2,3]}}
puts a_hash.get_deep(:one, :two ).inspect # => {:three=>"asd"}
puts a_hash.get_deep(:one, :two, :three ).inspect # => "asd"
puts a_hash.get_deep(:one, :two, :three, :four).inspect # => nil
puts a_hash.get_deep(:one, :arr ).inspect # => [1,2,3]
puts a_hash.get_deep(:one, :arr, :too_deep ).inspect # => nil
Le dernier exemple devrait soulever une exception: "Symbole d'index de tableau (TypeError)" s'il n'a pas été gardé par ce vilain "is_a?(Hash)".