Ruby-on-rails Rails 加载 YAML 以散列并按符号引用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7072986/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rails load YAML to hash and reference by symbol
提问by Michael K Madison
I am loading a YAML file in Rails 3.0.9 like this:
我在 Rails 3.0.9 中加载一个 YAML 文件,如下所示:
APP_CONFIG = YAML.load(File.read(File.expand_path('../app.yml', __FILE__)))
It loads the all of the contents like hierarchical hashes, no problem. The part I don't like is the fact that the hashes can only be accessed with single or double quotes but not a symbol.
它加载所有内容,如分层哈希,没问题。我不喜欢的部分是哈希值只能用单引号或双引号访问,而不能用符号访问。
APP_CONFIG['mailer']['username'] # works fine
APP_CONFIG[:mailer][:username] # doesn't
Any thoughts?
有什么想法吗?
回答by Rob Di Marco
Try using the HashWithIndifferentAccesslike
尝试使用HashWithIndifferentAccess 之类的
APP_CONFIG = HashWithIndifferentAccess.new(YAML.load(File.read(File.expand_path('../app.yml', __FILE__))))
回答by istvanp
An alternative solution is to have the keys which you wish to access as a symbol prepended with a colon. For example:
另一种解决方案是将您希望访问的密钥作为带有冒号的符号。例如:
default: &default
:symbol: "Accessed via a symbol only"
string: "Accessed via a string only"
development:
<<: *default
test:
<<: *default
production:
<<: *default
Later you can then access these like so:
稍后您可以像这样访问这些:
APP_CONFIG[:symbol]
APP_CONFIG['string']
Note that I am using YAML::ENGINE.yamler = "syck". Not sure if this works with psych. (Psych definitely won't support key merging as I showed in the example though.)
请注意,我正在使用YAML::ENGINE.yamler = "syck". 不确定这是否适用于psych. (尽管我在示例中展示了 Psych 绝对不会支持密钥合并。)
About using HashWithIndifferentAccess:using it has the side effect of creating duplicate keys: one for symbol access and one for string access. This might be nefarious if you pass around YAML data as arrays. Be aware of this if you go with that solution.
关于使用HashWithIndifferentAccess:使用它有创建重复键的副作用:一个用于符号访问,另一个用于字符串访问。如果您将 YAML 数据作为数组传递,这可能是有害的。如果您使用该解决方案,请注意这一点。
回答by zentralmaschine
If you are working in Ruby on Rails, You might want to take a look at symbolize_keys(), which does exactly what the OP asked for. If the hash is deep,you can use deep_symbolize_keys(). Using this approach, the answer is
如果您在 Ruby on Rails 中工作,您可能想看看Symbol_keys(),它完全符合 OP 的要求。如果散列很深,你可以使用deep_symbolize_keys(). 使用这种方法,答案是
APP_CONFIG = YAML.load(File.read(File.expand_path('../app.yml', __FILE__))).deep_symbolize_keys
回答by fotanus
This is the same from the selected answer, but with a better syntax:
这与所选答案相同,但语法更好:
YAML.load(File.read(file_path)).with_indifferent_access
回答by Michael K Madison
There is another potential answer I discovered while digging around.
我在挖掘时发现了另一个潜在的答案。
You can forgo HashWithIndifferentAccess.new by instead adding this to the top of your YAML files:
您可以通过将其添加到 YAML 文件的顶部来放弃 HashWithIndifferentAccess.new:
--- !map:HashWithIndifferentAccess
then simply YAML.load like normal. The only trick is that rails needs to already be loaded if you are doing this in your environment for use in initializers, etc. (like I am).
然后像往常一样简单地使用 YAML.load。唯一的技巧是,如果您在您的环境中执行此操作以用于初始化程序等(就像我一样),则需要已经加载 rails。
回答by Vladimir Krivchenko
- Rails has a special method to symbolize keys.
- You can use load_file method and get rid of File.read
- Not sure if you need expand_path also, the default directory is rails root.
- Rails 有一种特殊的方法来符号化键。
- 您可以使用 load_file 方法并摆脱 File.read
- 不确定是否还需要 expand_path,默认目录是 rails root。
I'd write it that simple:
我会这么简单地写:
YAML::load_file('app.yml').symbolize_keys
YAML::load_file('app.yml').symbolize_keys
回答by Nav
If you're using pure Ruby (i.e. no Rails), you could intermediately change to JSON format. The JSON lib's parsemethod can symbolize keys.
如果您使用纯 Ruby(即没有 Rails),您可以暂时更改为 JSON 格式。JSON 库的parse方法可以符号化键。
http://ruby-doc.org/stdlib-2.0.0/libdoc/json/rdoc/JSON.html#method-i-parse
http://ruby-doc.org/stdlib-2.0.0/libdoc/json/rdoc/JSON.html#method-i-parse
Here's what I mean:
这就是我的意思:
JSON.parse(JSON.dump(YAML.load_file(File.expand_path('../app.yml', __FILE__))), symbolize_names: true)
Note: This adds overhead of conversion to and from json.
注意:这会增加与 json 之间的转换开销。
回答by Tilo
You are probably used to the params hash in Rails, which is actually a HashWithIndifferentAccess rather than a standard ruby Hash object. This allows you to use either strings like 'action' or symbols like :action to access the contents.
您可能已经习惯了 Rails 中的 params 散列,它实际上是一个 HashWithIndifferentAccess 而不是标准的 ruby Hash 对象。这允许您使用像 'action' 这样的字符串或像 :action 这样的符号来访问内容。
With a HashWithIndifferentAccess, you will get the same results regardless of what you use, but keep in mind this only works on HashWithIndifferentAccess objects.
使用 HashWithIndifferentAccess,无论您使用什么,您都将获得相同的结果,但请记住,这仅适用于 HashWithIndifferentAccess 对象。
So to make this work with YAML, you'll have to load the result of YAML.load into a HashWithIndifferentAccess, like so:
因此,要使用 YAML 进行此操作,您必须将 YAML.load 的结果加载到 HashWithIndifferentAccess 中,如下所示:
APP_CONFIG = HashWithIndifferentAccess.new( YAML.load(File.read(File.expand_path('../app.yml', __FILE__))) )
回答by skalee
Just use appropriate option in your YAML parser. For instance, symbolize_namesin Psych:
只需在您的 YAML 解析器中使用适当的选项。例如,symbolize_names在 Psych 中:
APP_CONFIG = YAML.load(File.read(File.expand_path('../app.yml', __FILE__)), symbolize_names: true)
See RDoc: https://ruby-doc.org/stdlib-2.6.1/libdoc/psych/rdoc/Psych.html#method-c-load.
请参阅 RDoc:https: //ruby-doc.org/stdlib-2.6.1/libdoc/psych/rdoc/Psych.html#method-c-load。
回答by lobati
I usually don't use HashWithIndifferentAccessjust to avoid confusion and prevent inconsistencies in the way that it is accessed, so what I would do instead is tack on a .deep_symbolize_keysto get the whole thing in symbol key form.
我通常不HashWithIndifferentAccess只是为了避免混淆和防止访问方式的不一致而使用它,所以我会做的是添加 a.deep_symbolize_keys以符号键形式获取整个内容。

