【问题标题】:Ruby Rails Hash IssueRuby Rails 哈希问题
【发布时间】:2012-08-30 07:40:15
【问题描述】:

所以我现在一直在为一个问题苦苦挣扎,但似乎一无所获......

当我循环一个散列时,问题存在,大约在第 3 级深度。

所以我的代码看起来有点像:

request[:items][:location_item].each do |locaton_item|
  pp location_item[:name]
  location_item[:items][:sub_area_option_item].each do |sub_area_option_item|
    pp sub_area_option_item[:name]
    sub_area_option_item[:items][:option_item].each do |option_item|
      option_item[:name] <- THIS IS WHERE MY CODE BREAKS
    end
  end
end

失败的原因是循环的这个特定部分有 2 个不同的变体,一个有无限数量的“option_item”,一个只有一个“option_item”。它不是将单个“option_item”发回给我,而是循环通过这个“option_item”并且没有找到这个特定的字段。当只找到一个对象仍将其作为数组返回时如何强制它的任何想法?

更新(05/092012)

TypeError - 符号作为数组索引

如果我从哈希中删除单个“option_item”,甚至使用条件语句对其进行过滤,则不会出现此错误。

作为之前的示例的另一个更新,这里是代码:

request[:items][:house_option_item][:items][:location_option_item].each do |location_option_item|
  pp location_option_item.try(:[], :location).try(:[], :name)
  # pp location_option_item[:location][:name]

  location_option_item[:items][:sub_area_option_item].each do |sub_area_option_item|
    pp "--" + sub_area_option_item[:sub_area][:name] + "--" + sub_area_option_item[:sub_area][:id]
    count = 0

    # pp sub_area_option_item[:items].length
    # pp "+++++++++++++++++"

    # if sub_area_option_item[:sub_area][:name] != "Conservatory"
      [sub_area_option_item[:items][:option_item]].each do |option_item_key_info|

        pp "----"
        pp option_item_key_info[:usage_name]

      end
    # end

  end
end

示例数据(略):

{:"@xmlns:i"=>"http://www.w3.org/2001/XMLSchema-instance",
 :"@xmlns:a"=>"http://schemas.datacontract.org/2004/07/RXTypes",
 :items=>
  {:house_option_item=>
    {:design=>
      {:house_style=>nil,
       :sales_name=>nil,
       :sq_ft=>"0",
       :"@xmlns:b"=>"http://schemas.datacontract.org/2004/07/",
       :arch_ref=>"D3H102.1",
       :marketing_name=>"Warwick",
       :num_beds=>"0"},
     :items=>
      {:location_option_item=>
        [{:location=>{:sort_order=>"0", :name=>"Eat", :id=>"1"},
          :items=>
           {:sub_area_option_item=>
             [{:sub_area=>
                {:location_id=>"7",
                 :sort_order=>"0",
                 :name=>"Conservatory",
                 :id=>"31"},
               :items=>
                {:option_item=>
                  {:lead_days=>"0",
                   :collection_code=>"NEWHE01",
                   :usage_name=>"Conservatory",
                   :max_qty=>"1",
                   :is_a_bundle=>false,
                   :only_order_bundle=>false,
                   :sub_area=>"Conservatory",
                   :key_info=>
                    {:specification=>
                      "PVC-U 'Edwardian' style Conservatory in white with high performance toughened glass double glazed windows and 600mm (approx) dwarf base wall internally and externally. Conservatory to include fan and light, electric heater, double power point and ceramc floor tiling selected from tile choice . Size of Conservatory to be as follows: 3.2 x 3.1 metre (Availabil
ity will be subject to ground levels/conditions)",
                     :description=>"Conservatory",
                     :image_url=>"/2012/8/10/334_web.jpg",
                     :item_id=>"3",
                     :thumbnail_url=>"/2012/8/10/334_thumb.jpg"},
                   :build_stage_id=>"0",
                   :location=>"Building",
                   :option_flag=>"67",
                   :bundle_items=>nil,
                   :price=>"8950",
                   :choice_items=>nil,
                   :spec_level=>"85"}}},
              {:sub_area=>
                {:location_id=>"7",
                 :sort_order=>"0",
                 :name=>"Doors",
                 :id=>"32"},
               :items=>
                {:option_item=>
                  [{:lead_days=>"0",
                    :collection_code=>"NEWHE01",
                    :usage_name=>"Front Door",
                    :max_qty=>"0",
                    :is_a_bundle=>false,
                    :only_order_bundle=>false,
                    :sub_area=>"Doors",
                    :key_info=>
                     {:specification=>
                       "GRP pre-finished door with patterned glass manufactured by IG. Style of door to be all as indicated on house plan, finished in solid colour externally & white finish internally. Frame to be UPVC. Please refer to the External Finishing schedule to confirm the external finish selected for each property. The paint finish to be one of the New Heritage Colours - Camouflage beige
 - BS381 389, Dk camouflage desert sand - BS381 420, Wine Red - RAL 3005, Braemar - BS4800 - 14C35, Deep Brunswick Green - BS381 227 and White. Door complete with lever handle furniture, multi point lock system, sleeved letterplate, viewer and door chain in black japanned finish externally & chrome lever handle furniture internally.",
                      :description=>"GRP Front door",
                      :image_url=>nil,
                      :item_id=>"4",
                      :thumbnail_url=>nil},
                    :build_stage_id=>"0",
                    :location=>"Building",
                    :option_flag=>"88",
                    :bundle_items=>nil,
                    :price=>"0",
                    :choice_items=>
                     {:option_item_key_info=>
                       [{:specification=>nil,
                         :description=>"NG42 Diamond",
                         :image_url=>"/2012/8/21/485_web.jpg",
                         :item_id=>"211",
                         :thumbnail_url=>"/2012/8/21/485_thumb.jpg"},
                        {:specification=>nil,
                         :description=>"NG21 Square",
                         :image_url=>"/2012/8/21/486_web.jpg",
                         :item_id=>"212",
                         :thumbnail_url=>"/2012/8/21/486_thumb.jpg"},
                        {:specification=>nil,
                         :description=>"NG51 Square",
                         :image_url=>"/2012/8/21/487_web.jpg",
                         :item_id=>"213",
                         :thumbnail_url=>"/2012/8/21/487_thumb.jpg"},
                        {:specification=>nil,
                         :description=>"NG42 Rectangle",
                         :image_url=>"/2012/8/21/488_web.jpg",
                         :item_id=>"214",
                         :thumbnail_url=>"/2012/8/21/488_thumb.jpg"}]},
                    :spec_level=>"83"},
                   {:lead_days=>"0",
                    :collection_code=>"NEWHE01",
                    :usage_name=>"Front Door",
                    :max_qty=>"0",
                    :is_a_bundle=>false,
                    :only_order_bundle=>false,
                    :sub_area=>"Doors",
                    :key_info=>
                     {:specification=>
                       "GRP pre-finished door with patterned glass manufactured by IG. Style of door to be all as indicated on house plan, finished in solid colour externally & white finish internally. Frame to be UPVC. Please refer to the External Finishing schedule to confirm the external finish selected for each property. The paint finish to be one of the New Heritage Colours - Camouflage beige
 - BS381 389, Dk camouflage desert sand - BS381 420, Wine Red - RAL 3005, Braemar - BS4800 - 14C35, Deep Brunswick Green - BS381 227 and White. Door complete with lever handle furniture, multi point lock system, sleeved letterplate, viewer and door chain in black japanned finish externally & chrome lever handle furniture internally.",
                      :description=>"GRP Front door",
                      :image_url=>nil,
                      :item_id=>"4",
                      :thumbnail_url=>nil},
                    :build_stage_id=>"0",
                    :location=>"Building",
                    :option_flag=>"88",
                    :bundle_items=>nil,
                    :price=>"0",
                    :choice_items=>
                     {:option_item_key_info=>
                       [{:specification=>nil,
                         :description=>"NG42 Diamond",
                         :image_url=>"/2012/8/21/485_web.jpg",
                         :item_id=>"211",
                         :thumbnail_url=>"/2012/8/21/485_thumb.jpg"},
                        {:specification=>nil,
                         :description=>"NG21 Square",
                         :image_url=>"/2012/8/21/486_web.jpg",
                         :item_id=>"212",
                         :thumbnail_url=>"/2012/8/21/486_thumb.jpg"},
                        {:specification=>nil,
                         :description=>"NG51 Square",
                         :image_url=>"/2012/8/21/487_web.jpg",
                         :item_id=>"213",
                         :thumbnail_url=>"/2012/8/21/487_thumb.jpg"},
                        {:specification=>nil,
                         :description=>"NG42 Rectangle",
                         :image_url=>"/2012/8/21/488_web.jpg",
                         :item_id=>"214",
                         :thumbnail_url=>"/2012/8/21/488_thumb.jpg"}]},
                    :spec_level=>"83"},
                   {:lead_days=>"0",
                    :collection_code=>"NEWHE01",
                    :usage_name=>"Front Door",
                    :max_qty=>"0",
                    :is_a_bundle=>false,
                    :only_order_bundle=>false,
                    :sub_area=>"Doors",
                    :key_info=>
                     {:specification=>
                       "GRP pre-finished door with patterned glass manufactured by IG. Style of door to be all as indicated on house plan, finished in solid colour externally & white finish internally. Frame to be UPVC. Please refer to the External Finishing schedule to confirm the external finish selected for each property. The paint finish to be one of the New Heritage Colours - Camouflage beige
 - BS381 389, Dk camouflage desert sand - BS381 420, Wine Red - RAL 3005, Braemar - BS4800 - 14C35, Deep Brunswick Green - BS381 227 and White. Door complete with lever handle furniture, multi point lock system, sleeved letterplate, viewer and door chain in black japanned finish externally & chrome lever handle furniture internally.",
                      :description=>"GRP Front door",
                      :image_url=>nil,
                      :item_id=>"4",
                      :thumbnail_url=>nil},
                    :build_stage_id=>"0",
                    :location=>"Building",
                    :option_flag=>"88",
                    :bundle_items=>nil,
                    :price=>"0",
                    :choice_items=>
                     {:option_item_key_info=>
                       [{:specification=>nil,
                         :description=>"NG42 Diamond",
                         :image_url=>"/2012/8/21/485_web.jpg",
                         :item_id=>"211",
                         :thumbnail_url=>"/2012/8/21/485_thumb.jpg"},
                        {:specification=>nil,
                         :description=>"NG21 Square",
                         :image_url=>"/2012/8/21/486_web.jpg",
                         :item_id=>"212",
                         :thumbnail_url=>"/2012/8/21/486_thumb.jpg"},
                        {:specification=>nil,
                         :description=>"NG51 Square",
                         :image_url=>"/2012/8/21/487_web.jpg",
                         :item_id=>"213",
                         :thumbnail_url=>"/2012/8/21/487_thumb.jpg"},
                        {:specification=>nil,
                         :description=>"NG42 Rectangle",
                         :image_url=>"/2012/8/21/488_web.jpg",
                         :item_id=>"214",
                         :thumbnail_url=>"/2012/8/21/488_thumb.jpg"}]},
                    :spec_level=>"83"},

【问题讨论】:

  • TypeError - 符号作为数组索引
  • 在你的代码的第一行,block参数是locaton_item,但是在第二行和第三行是location_item
  • @Anthony :then option_item 是一个数组,而不是一个哈希
  • 不管怎样,希望不要在这里听起来很愚蠢,如果它是一个数组或散列,它不应该仍然可以通过 variable_name[:item_name] 访问吗?
  • 哈希可以通过符号访问的原因是因为哈希包含键值对(因此您可以通过键访问它)。数组只是一个值列表 - 因此只能通过数组中的索引(即整数)访问它

标签: ruby-on-rails ruby arrays ruby-on-rails-3 hash


【解决方案1】:

如果 只有一个 option_item,Krista 的示例将有效,但如果有更多则无效。我会添加 flatten 并将其调整为:

[sub_area_option_item[:items][:option_item]].flatten.each do |option_item|
  option_item[:name]
end

它周围的 [] 确保它是一个数组。 flatten 确保如果它已经是一个数组,则删除 [] 的额外层,例如:

['a'].flatten
=> ["a"]
[['a','b','c',]].flatten
=> ["a", "b", "c"]

【讨论】:

  • Brilliant mate...似乎按预期完美运行。您说的是正确的,在某些情况下返回了多个块。谢谢!
  • @Taryn - 谢谢!我实际上不知道flatten - 这是件好事 :)
【解决方案2】:

据我所知,循环的第二部分应该是问题所在 - 考虑到您的源代码和示例数据

01: request[:items][:house_option_item][:items][:location_option_item].each do |location_option_item|

02:   location_option_item[:items][:sub_area_option_item].each do |sub_area_option_item|
03:      count = 0
04:      # if sub_area_option_item[:sub_area][:name] != "Conservatory"
05:      [sub_area_option_item[:items][:option_item]].each do |option_item_key_info|
06:          pp option_item_key_info[:usage_name]
07:      end
08:      # end

09:   end
10: end

请注意,第 01 行最终会访问 location_option_item,在上面的示例中是:

:location_option_item=>
    [{:location=>{:sort_order=>"0", :name=>"Eat", :id=>"1"},
      :items=>
       {:sub_area_option_item=>
         [{:sub_area=>
            {:location_id=>"7",
             :sort_order=>"0",
             :name=>"Conservatory",
             :id=>"31"},
           :items=>
            {:option_item=>
              {:lead_days=>"0",
               :collection_code=>"NEWHE01",
               ........ etc .......

注意location_option_item 是键,它的值是一个数组。

因此,我的猜测是这条线是问题(02):location_option_item[:items]

由于 location_option_item 是一个数组,因此您无法从中访问 :items 符号。

如果您想获得items,则更像是:

location_option_item[1][:items]

【讨论】:

  • 谢谢 Krista,但问题是可能存在多个“option_item”的情况。
猜你喜欢
  • 2011-04-15
  • 2014-04-09
  • 2012-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多