Ruby Rails哈希问题



所以我已经为一个问题挣扎了一段时间,似乎没有任何进展。。。

当我在第三层深处循环哈希时,问题就存在了。

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

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_iitem"中循环,却找不到这个特定的字段。当只发现一个对象仍将其作为数组返回时,如何强制它?

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

Krista的例子如果只有一个option_item就可以了,但如果有更多的option_item就不行了。我会添加压平并将其调整为:

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

它周围的[]确保它是一个数组。压平可以确保如果它已经是一个数组,那么你可以去除额外的[]层,例如:

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

据我所知,循环的第二部分应该是问题所在——给定源代码和样本数据

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]

最新更新