【问题标题】:Rails 3.1 hash each gives TypeErrorRails 3.1 哈希每个都给出 TypeError
【发布时间】:2011-10-27 15:56:26
【问题描述】:

我有 hash(Hash.from_xml) 看起来像这样(来自检查):

{
"FileName"=>"hofplayers.xml",
"Version"=>"1.0",
"UserID"=>"3955847", 
"FetchedDate"=>"2011-08-16 00:41:02", 
"PlayerList"=>{
    "Player"=>{
        "PlayerId"=>"92121587", 
        "FirstName"=>"Gennady", 
        "NickName"=>nil, 
        "LastName"=>"Buzykin", 
        "Age"=>"45", 
        "NextBirthday"=>"2011-09-24 22:10:00", 
        "ArrivalDate"=>"2008-03-08 16:37:00", 
        "ExpertType"=>"15", 
        "HofDate"=>"2010-01-23 16:10:00", 
        "HofAge"=>"40"
        }
    }
}

然后我会迭代每一个,因为可以有不止一个玩家:

<% @hof['PlayerList']['Player'].each do |player| %>
    <%= player['NickName']%>
<% end %>

它失败了 TypeError: can't convert String into Integer。但是当有多个玩家时,它就像我想要的那样工作。问题似乎是,当有单个玩家时,每个人都制作数组而不是哈希,player.inspect 给出:

 ["PlayerId", "92121587"]
 ["FirstName", "Gennady"]
 ["NickName", nil]
 ["LastName", "Buzykin"]
 ["Age", "45"]
 ["NextBirthday", "2011-09-24 22:10:00"]
 ["ArrivalDate", "2008-03-08 16:37:00"]
 ["ExpertType", "15"]
 ["HofDate", "2010-01-23 16:10:00"]
 ["HofAge", "40"]

代替

 {
     "PlayerId"=>"25787535", 
     "FirstName"=>"Rico", 
     "NickName"=>nil, 
     "LastName"=>"van Oostveen", 
     "Age"=>"42", 
     "NextBirthday"=>"2011-10-23 22:18:00", 
     "ArrivalDate"=>"2006-02-11 18:43:00", 
     "ExpertType"=>"2", 
     "HofDate"=>"2010-04-25 22:01:00", 
     "HofAge"=>"38"
 }

那么我做错了什么?

【问题讨论】:

  • 当玩家超过一个时,PlayerList会变成一个数组吗?还是你得到 PlayerList => {"Player1" => {...}, "Player2" => {...}}
  • @phillee 变成了一个数组。

标签: ruby-on-rails ruby hash typeerror


【解决方案1】:

当您在哈希上执行each 时,您会得到一个键/值对列表,然后您尝试使用字符串对这些对进行索引,这会给您带来错误。您无法更改 from_xml 所做的事情,但您可以解决它。

您可以在控制器中修补哈希:

if(@hof['PlayerList']['Player'].is_a?(Hash))
    @hof['PlayerList']['Player'] = [ @hof['PlayerList']['Player'] ]
end
# or
if(!@hof['PlayerList']['Player'].is_a?(Array))
    @hof['PlayerList']['Player'] = [ @hof['PlayerList']['Player'] ]
end

如果你没有你所期望的,你只需将它变成一个包含一个元素的数组;您选择哪种测试取决于您期望从from_xml 获得什么样的东西,但我倾向于“非数组”检查,因为它与您想要做的完全匹配。

或者您可以尝试在您的视图中对其进行排序:

<% [ @hof['PlayerList']['Player'] ].flatten(1).each do |player| %>

这基本上将您拥有的所有内容包装在一个数组中,然后将其展平一层,如果您已经有一个数组,则需要调用flatten(1)。如果你从一个数组开始,那么[ ].flatten(1) 是一个空操作(flatten 调用将撤消[] 所做的事情),除了浪费一点 CPU 时间外,不会产生任何明显的影响;如果你从一个哈希开始,那么[ ... ] 会将它变成一个数组,flatten 不会做任何事情(但会浪费一点 CPU)。

【讨论】:

  • Flatten 似乎工作正常,但我明天会更仔细地检查。
【解决方案2】:

想到的一件事是:

<% @hof['PlayerList']['Player'].each do |player| %>
  <%= player['NickName']%>
<% end %>

不循环播放器。它循环遍历“播放器”哈希的名称/值对。编辑。我的意思是它会循环遍历 key1、value1、key2、value2、key3 等。循环的每次迭代一个...

我想你会想要这样的东西:

<% @hof['PlayerList'].each_pair do |player, player_data| %>
  <%= player_data['NickName']%>
<% end %>

【讨论】:

    猜你喜欢
    • 2020-07-18
    • 2017-11-23
    • 2014-07-16
    • 1970-01-01
    • 2021-10-17
    • 2018-10-05
    • 2016-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多