Ruby Rails哈希问题

时间:2012-09-05 14:37:19

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

所以我一直在努力解决一个问题,现在似乎无处可去......

当我在第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

这是失败的原因是因为循环的这个特定部分有两个不同的变体,一个存在无限量的“option_items”,另一个只有一个“option_item”。它没有向我发回单个“option_item”,而是循环遍历此“option_item”而没有找到此特定字段。当发现只有一个对象仍然将其作为数组返回时,如何强制它的任何想法?

UPDATE(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"},

2 个答案:

答案 0 :(得分: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]

答案 1 :(得分:2)

如果只有一个option_item,那么Krista的示例将有效,但如果还有更多则不行。我会添加展平并将其调整为:

[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"]