Rails 3.1 hash每个都给出TypeError

时间:2011-08-15 23:13:22

标签: ruby-on-rails ruby hash typeerror

我有哈希(Hash.from_xml)看起来像这样(来自inspect):

{
"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而失败:无法将String转换为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"
 }

那么我做错了什么?

2 个答案:

答案 0 :(得分:0)

当您在Hash上执行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)。

答案 1 :(得分:0)

脑海中浮现的一件事是:

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

不会循环播放器。它循环遍历'Player'哈希的名称/值对。编辑。通过这个我的意思是它将循环通过key1,value1,key2,value2,key3,...等。每次迭代循环一次......

我认为你想要这样的东西:

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