Je charge un fichier YAML dans Rails 3.0.9 comme ceci:
APP_CONFIG = YAML.load(File.read(File.expand_path('../app.yml', __FILE__)))
Il charge tout le contenu comme des hachages hiérarchiques, pas de problème. Ce que je n’aime pas, c’est que les hachages ne sont accessibles qu’avec des guillemets simples ou doubles, mais pas un symbole.
APP_CONFIG['mailer']['username'] # works fine
APP_CONFIG[:mailer][:username] # doesn't
Des pensées?
Essayez d'utiliser le HashWithIndifferentAccess comme
APP_CONFIG = HashWithIndifferentAccess.new(YAML.load(File.read(File.expand_path('../app.yml', __FILE__))))
Une autre solution consiste à placer les touches auxquelles vous souhaitez accéder sous la forme d'un symbole précédé de deux points. Par exemple:
default: &default
:symbol: "Accessed via a symbol only"
string: "Accessed via a string only"
development:
<<: *default
test:
<<: *default
production:
<<: *default
Plus tard, vous pourrez alors accéder à ceux-ci comme ceci:
APP_CONFIG[:symbol]
APP_CONFIG['string']
Notez que j'utilise YAML::ENGINE.yamler = "syck"
. Vous ne savez pas si cela fonctionne avec psych
. (Psych ne supportera certainement pas la fusion de clé comme je l’ai montré dans l’exemple cependant).
À propos de l'utilisation de HashWithIndifferentAccess
: son utilisation a pour effet secondaire de créer des clés dupliquées: une pour l'accès aux symboles et une pour l'accès aux chaînes. Cela pourrait être néfaste si vous transmettez des données YAML sous forme de tableaux. Soyez conscient de cela si vous optez pour cette solution.
Si vous travaillez dans Ruby on Rails, jetez un oeil à symbolize_keys () , qui fait exactement ce que l'OP a demandé. Si le hachage est profond, vous pouvez utiliser deep_symbolize_keys()
. En utilisant cette approche, la réponse est
APP_CONFIG = YAML.load(File.read(File.expand_path('../app.yml', __FILE__))).deep_symbolize_keys
C'est la même chose pour la réponse sélectionnée, mais avec une meilleure syntaxe:
YAML.load(File.read(file_path)).with_indifferent_access
Il y a une autre réponse potentielle que j'ai découverte en fouillant.
Vous pouvez renoncer à HashWithIndifferentAccess.new en ajoutant ceci en haut de vos fichiers YAML:
--- !map:HashWithIndifferentAccess
alors simplement YAML.load comme d'habitude. La seule astuce est que Rails doit déjà être chargé si vous le faites dans votre environnement pour une utilisation dans les initialiseurs, etc. (comme je le suis).
Vous êtes probablement habitué au hachage params dans Rails, qui est en fait un objet HashWithIndifferentAccess plutôt qu'un objet Ruby Hash standard. Cela vous permet d'utiliser des chaînes telles que "action" ou des symboles tels que: action pour accéder au contenu.
Avec HashWithIndifferentAccess, vous obtiendrez les mêmes résultats quel que soit ce que vous utilisez, mais gardez à l'esprit que cela ne fonctionne que sur les objets HashWithIndifferentAccess.
Donc, pour que cela fonctionne avec YAML, vous devrez charger le résultat de YAML.load dans un HashWithIndifferentAccess, comme ceci:
APP_CONFIG = HashWithIndifferentAccess.new( YAML.load(File.read(File.expand_path('../app.yml', __FILE__))) )
Si vous utilisez du pur Ruby (c’est-à-dire qu’il n’ya pas de Rails), vous pouvez passer au format JSON. La méthode parse
de la bibliothèque JSON peut symboliser les clés.
http://Ruby-doc.org/stdlib-2.0.0/libdoc/json/rdoc/JSON.html#method-i-parse
Voici ce que je veux dire:
JSON.parse(JSON.dump(YAML.load_file(File.expand_path('../app.yml', __FILE__))), symbolize_names: true)
Note: Ceci ajoute un temps système supplémentaire pour la conversion vers et depuis json.
D'habitude, je n'utilise pas HashWithIndifferentAccess
simplement pour éviter la confusion et éviter les incohérences dans la façon dont on y accède. Ce que je ferais plutôt, c'est d'utiliser un .deep_symbolize_keys
pour obtenir le tout sous forme de clé symbolique.