0

我现在正在为Rhodes移动应用程序框架学习 Ruby,遇到了这个问题:Rhodes 的 HTTP 客户端将 JSON 响应解析为 Ruby 数据结构,例如

puts @params # prints {"body"=>{"results"=>[]}}

由于这里的键“body”是一个字符串,所以我的第一次尝试@params[:body]失败了 (is nil) 而它必须是@params['body']. 我觉得这是最不幸的。

有人可以解释为什么字符串和符号具有不同的哈希值的理由,即:body.hash != 'body'.hash在这种情况下?

4

3 回答 3

6

符号和字符串有两种不同的用途。

字符串是您熟悉的老朋友:可变且可垃圾回收。每次使用字符串文字或#to_s方法时,都会创建一个新字符串。您使用字符串来构建 HTML 标记、将文本输出到屏幕等等。

另一方面,符号是不同的。每个符号只存在于一个实例中并且它始终存在(即,它不是垃圾收集的)。因此,您应该非常小心地制作新符号(String#to_sym:''文字)。这些属性使它们成为命名事物的良好候选者。例如,在宏中使用符号(如attr_reader :foo.

如果您从外部源获取哈希(例如,您反序列化了 JSON 响应)并且想要使用符号来访问其元素,那么您可以使用 HashWithIndifferentAccess(正如其他人指出的那样),或者从 ActiveSupport 调用帮助器方法:

require 'active_support/core_ext'

h = {"body"=>{"results"=>[]}}
h.symbolize_keys # => {:body=>{"results"=>[]}}
h.stringify_keys # => {"body"=>{"results"=>[]}}

请注意,它只会触及顶层,不会进入子哈希。

于 2012-05-02T14:03:45.240 回答
4

符号和字符串从不==

:foo == 'foo'  # => false

这是一个(非常合理的)设计决定。毕竟,它们有不同的类、方法,一个是可变的,另一个不是,等等......

因此,它们永远是强制性的eql?

:foo.eql? 'foo'  # => false

两个对象eql?通常不具有相同的散列,但即使它们具有相同的散列,散列查找也会使用hash then eql?。所以你的问题真的是“为什么符号和字符串不是eql?”。

Rails 使用HashWithIndifferentAccess字符串或符号无差别地访问。

于 2012-05-02T14:26:38.657 回答
2

在 Rails 中,params 哈希实际上是一个 HashWithIndifferentAccess 而不是标准的 ruby​​ 哈希对象。这允许您使用像 'action' 这样的字符串或像 :action 这样的符号来访问内容。

无论您使用什么,您都将获得相同的结果,但请记住,这仅适用于 HashWithIndifferentAccess 对象。

复制自:Params 哈希键作为符号与字符串

于 2012-05-02T14:02:22.137 回答