web-dev-qa-db-fra.com

Les rails chargent YAML vers le hachage et la référence par symbole

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?

58
Michael K Madison

Essayez d'utiliser le HashWithIndifferentAccess comme

APP_CONFIG = HashWithIndifferentAccess.new(YAML.load(File.read(File.expand_path('../app.yml', __FILE__))))
74
Rob Di Marco

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. 

31
istvanp

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
25
zentralmaschine

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 
15
fotanus

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). 

11
Michael K Madison

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__)))   )
2
Tilo

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.

2
Nav

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.

0
lobati