Ruby哈希数组返回键而不是值?

时间:2016-10-06 23:25:11

标签: arrays ruby hash

[1] pry(main)> o.items
=> [{"78"=>"{\"size\"=>\"96\", \"side\"=>[]}"}]

[2] pry(main)> o.items[0]
=> {"78"=>"{\"size\"=>\"96\", \"side\"=>[]}"}

[3] pry(main)> o.items[0]['78']
=> "{\"size\"=>\"96\", \"side\"=>[]}"

[4] pry(main)> o.items[0]['78']["side"]
=> "side"

不是第4行应该返回一个空数组吗?怎么回来"那边"?

修改

我发现在保存哈希数组之后会发生这种情况(它是postgresql上的hstore数组)。

E.g 这会按预期返回一个哈希值。

o.items << {78 => {"size" => 1, "side" => []}}
o.items
=> [{"78"=> {"size"=>"1", "side"=>[]}}]  

但保存后

o.save
o.items
=> [{"78"=>"{\"size\"=>\"96\", \"side\"=>[]}"}]

我最终做了eval(o.items [0] [&#39; 78&#39;]),在对哈希进行任何更改并进行更新之前将字符串转换回哈希值。这似乎是非常不必要的,有更好的选择吗?

2 个答案:

答案 0 :(得分:2)

正如评论者指出的那样,问题在于数据类型。您认为该值是一个哈希值,因为它实际上是一个字符串。逃脱的双引号是这里的线索。

"{\"size\"=>\"96\", \"side\"=>[]}"

VS

{"size"=>"96", "side"=>[]}

看到区别?

当你有一个字符串并使用String#[]方法访问它时,它会返回该字符串。文档说:

If a match_str is given, that string is returned if it occurs in the string.

检查此链接以获取更多详细信息: http://ruby-doc.org/core-2.3.0/String.html#method-i-5B-5D

答案 1 :(得分:1)

如果将其保存到Rails属性中,则需要正确处理该类数据。最好使用以下方法之一完成此操作:

  • 使用JSON列类型存储任意结构。
  • 使用serialize标记列以处理任意数据。

MySQL 5.7和Postgres 9.3或更高版本支持JSON作为列类型,所以如果可能的话,我会指导这个方向。如果这不是一个选项,请使用常规TEXT列和serialize选项。

这将以ActiveRecord将重新构建回其原始格式的格式保存您的结构。您不必处理字符串化哈希。

你在这里无意中绊倒的是String#[]方法,它可以采用各种选项,但其中一个是要匹配的子字符串。在你的情况下,Ruby hash-as-string包含你正在寻找的短语,就像这样:

string = "ruby has strings"

string["ruby"]
# => "ruby"

string["test"]
# => nil

虽然这种特殊用法经常被忽视,但[]方法用于各种各样的事情。

警告:使用eval重新构建字符串中的哈希值实际上是最后的选择,如果有其他任何方式,应该避免使用,无论如何这有多尴尬或不方便。评估任意字符串是一个巨大的责任,好像任何事情应该进入可以被评估为代码的东西,它很容易危害你的系统。