[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;]),在对哈希进行任何更改并进行更新之前将字符串转换回哈希值。这似乎是非常不必要的,有更好的选择吗?
答案 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属性中,则需要正确处理该类数据。最好使用以下方法之一完成此操作:
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
重新构建字符串中的哈希值实际上是最后的选择,如果有其他任何方式,应该避免使用,无论如何这有多尴尬或不方便。评估任意字符串是一个巨大的责任,好像任何事情应该进入可以被评估为代码的东西,它很容易危害你的系统。