Rails加载YAML以哈希并按符号引用

Mic*_*son 65 hash yaml symbols ruby-on-rails

我在Rails 3.0.9中加载一个YAML文件,如下所示:

APP_CONFIG = YAML.load(File.read(File.expand_path('../app.yml', __FILE__)))
Run Code Online (Sandbox Code Playgroud)

它加载所有内容,如分层哈希,没问题.我不喜欢的部分是哈希只能用单引号或双引号访问而不能用符号访问.

APP_CONFIG['mailer']['username']  # works fine
APP_CONFIG[:mailer][:username]    # doesn't
Run Code Online (Sandbox Code Playgroud)

有什么想法吗?

Rob*_*rco 77

尝试使用HashWithIndifferentAccess之类的

APP_CONFIG = HashWithIndifferentAccess.new(YAML.load(File.read(File.expand_path('../app.yml', __FILE__))))
Run Code Online (Sandbox Code Playgroud)

  • 看起来很好,但我不使用ActiveSupport (3认同)

ist*_*anp 34

另一种解决方案是将您希望访问的密钥作为带有冒号的符号进行访问.例如:

default: &default
  :symbol: "Accessed via a symbol only"
  string: "Accessed via a string only"

development:
  <<: *default

test:
  <<: *default

production:
  <<: *default
Run Code Online (Sandbox Code Playgroud)

之后您可以像这样访问这些:

APP_CONFIG[:symbol]
APP_CONFIG['string']
Run Code Online (Sandbox Code Playgroud)

请注意我正在使用YAML::ENGINE.yamler = "syck".不确定这是否有效psych.(尽管如我在示例中所示,Psych肯定不会支持键合并.)

关于使用HashWithIndifferentAccess:使用它具有创建重复键的副作用:一个用于符号访问,另一个用于字符串访问.如果您将YAML数据作为数组传递,这可能是邪恶的.如果你使用该解决方案,请注意这一点.


zen*_*ine 27

如果您使用的是Ruby on Rails,您可能需要查看symbolize_keys(),它完全符合OP的要求.如果哈希很深,你可以使用deep_symbolize_keys().使用这种方法,答案是

APP_CONFIG = YAML.load(File.read(File.expand_path('../app.yml', __FILE__))).deep_symbolize_keys
Run Code Online (Sandbox Code Playgroud)

  • `deep_symbolize_keys()`应该处理嵌套属性. (7认同)

fot*_*nus 17

这与选定的答案相同,但语法更好:

YAML.load(File.read(file_path)).with_indifferent_access 
Run Code Online (Sandbox Code Playgroud)


Mic*_*son 12

我在挖掘时发现了另一个潜在的答案.

您可以放弃HashWithIndifferentAccess.new,而不是将其添加到YAML文件的顶部:

--- !map:HashWithIndifferentAccess
Run Code Online (Sandbox Code Playgroud)

然后就像正常的YAML.load一样.唯一的技巧是如果你在你的环境中这样做以便在初始化器等中使用,就需要加载rails(就像我一样).


bbe*_*nno 8

Psych(又名 YAML)提供关键字参数:symbolize_names以将键加载为符号。参见方法参考

file_path = File.expand_path('../app.yml', __FILE__)
yaml_contents = File.read(file_path)
    
APP_CONFIG = YAML.safe_load(yaml_contents, symbolize_names: true)
Run Code Online (Sandbox Code Playgroud)


小智 7

  1. Rails有一种特殊的方法来象征密钥.
  2. 您可以使用load_file方法并删除File.read
  3. 不确定是否还需要expand_path,默认目录是rails root.

我写得那么简单:

YAML::load_file('app.yml').symbolize_keys


ska*_*lee 7

只需在 YAML 解析器中使用适当的选项即可。例如,symbolize_names在《心理学》中:

APP_CONFIG = YAML.load(File.read(File.expand_path('../app.yml', __FILE__)), symbolize_names: true)
Run Code Online (Sandbox Code Playgroud)

请参阅 RDoc:https://ruby-doc.org/stdlib-2.6.1/libdoc/psych/rdoc/Psych.html#method-c-load