2012-05-28 8 views
24

Ich habe ein nicht-Rails-Projekt, in dem ich einige Einstellungen aus einer YAML-Datei bin Laden:Hash mit indifferent Zugang

config = YAML::load(File.open("#{LOG_ROOT}/config/database.yml")) 

ich nur diesen Hash wie config["host"] zugreifen kann, config["username"] usw.

I will gleichgültigen Zugang, so kann ich sowohl :host und "host" verwenden.

Der Grund ist, einer der Edelsteine ​​in dem Projekt, an dem ich diesen Hash übergebe, scheint mit Symbolen darauf zuzugreifen und es scheitert derzeit.

Was ist der beste Weg, um einen Hash mit gleichgültigem Zugriff in diesem Szenario zu erstellen?

+10

Selbst wenn Sie nicht Schienen verwenden gibt es keinen Grund, warum Sie konnte einfach nicht 'require‚active_support/core_ext/hash/indifferent_access'', und es ist Ihre Lösung? – Casper

+2

Ich habe active_support gem nicht installiert und fragte mich, ob ich es installieren sollte, nur um diese Funktion zu bekommen. – Josnidhin

+0

Wenn Sie nicht möchten, kopieren Sie den Code in Ihren eigenen Hash mit einer indifferenten Zugriffsklasse. Ich habe die Lösung von Rails nicht angeschaut, aber ich habe selbst schon eine geschrieben, kann nicht mehr als 50 LOC sein. –

Antwort

15

Lassen Sie die Config-Hash-Wert für die Zeichenfolge Version des Schlüssels zurück:

config = {"host"=>"value1", "Username"=>"Tom"} 
config.default_proc = proc{|h, k| h.key?(k.to_s) ? h[k.to_s] : nil} 
p config[:host] #=> "value1" 

Die default_proc läuft jedes Mal, wenn ein Schlüssel nicht in der Hash gefunden wird. Beachten Sie, dass dies nur die Hälfte des gleichgültigen Zugriffs ist: config["host"] führt zu Null, wenn der Schlüssel :host vorhanden ist. Wenn das arbeiten hat:

config.default_proc = proc do |h, k| 
    case k 
    when String then sym = k.to_sym; h[sym] if h.key?(sym) 
    when Symbol then str = k.to_s; h[str] if h.key?(str) 
    end 
end 
+8

Dies funktioniert für den Zugriff über '[]', nicht jedoch für 'delete', wo Sie die korrekte Version von der Schlüssel, nur damit Sie wissen – iain

+2

Beachten Sie auch, dass es nicht verhindert, dass jemand zwei Schlüssel hinzufügen: "Host" und: Host mit verschiedenen Werten zugewiesen! Wenn Sie den Schlüssel "Host" in Ihrem Hash-und hinzufügen Schlüssel: Host Der zweite wird nicht überschreiben Der erste! – wrzasa

42

Sie verlieren nichts außer ein paar kB Speicherplatz, indem Sie das Active Support-Juwel installieren. In Ihrem Code benötigen Sie nur die gewünschte Funktion:

require 'active_support/core_ext/hash/indifferent_access' 

Auf diese Weise können Sie sicher sein, Sie werden immer etwas anderes zu vermasseln nicht Ihren Namensraum.

+1

Ja, aber dann Dinge wie diese brechen :(- "% {version}"% {version: 5} .with_indifferent_access.to_hash, weil ich intern Strings als anstelle von Symbolen verwendet :( –

+0

Interessante Beobachtung. Sie haben tatsächlich gelehrt Ich einen Trick, den ich nicht einmal hier kannte :-), und ich sehe, es funktioniert tatsächlich nicht mit diesen indifferenten Hashes von ActiveSupport.In der kurzen Zeit bin ich nicht in der Lage zu sagen, ob das behoben werden kann, aber Sie würden a Eine gute Idee für die Ruby - Community, wenn Sie den ActiveSupport - Entwicklern ein entsprechendes Ticket senden würden: –