【问题标题】:Ruby hash array returning key instead of value?Ruby哈希数组返回键而不是值?
【发布时间】:2016-10-06 23:25:10
【问题描述】:
[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 数组)。

例如 这会按预期返回一个哈希值。

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

但是保存后

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

我最终执行了 eval(o.items[0]['78']) 将字符串转换回哈希,然后再对哈希进行任何更改并进行更新。这似乎非常不必要,有更好的选择吗?

【问题讨论】:

  • 仔细看。 o.items[0]['78'] 是字符串,不是哈希。
  • @Aetherus 太棒了,谢谢
  • @Aetherus 这似乎回答了这个问题,你应该把它写成一个答案,这样它就更明显了。
  • 怎么会这样?
  • "foobar"["oba"]"oba""foobar"[/o.a/] 也是。你在一个字符串中搜索"side",找到了。

标签: arrays ruby hash


【解决方案1】:

正如评论者所指出的,问题出在数据类型上。当它实际上是一个字符串时,您认为该值是一个哈希值。转义的双引号是这里的线索。

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

{"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

【讨论】:

  • 我在我的问题中添加了更多关于这是如何发生的信息。在保存到我的 postgresql 数据库后,哈希的内部似乎被转换为字符串。解决此问题的唯一方法是将字符串转换回哈希以对其进行更新吗?
【解决方案2】:

如果将其保存到 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 从字符串重构散列确实是不得已的选项,如果有任何其他方法,无论多么尴尬,都应该避免使用或者不方便。评估任意字符串是一项巨大的责任,好像任何东西都应该进入可以作为代码评估的代码,这很容易破坏你的系统。

【讨论】:

    猜你喜欢
    • 2017-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多