Reputation: 977
So I have been struggling with an issue for a while now and seem to be getting nowhere...
The problem exists while I am looping through a hash, around the 3rd level deep.
So my code looks a little like:
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
The reason this is failing is because this particular part of the loop has 2 different variants, one where there is an infinite amount of "option_items" and one where there is only one "option_item". Instead of sending me back the single "option_item" it is looping through this "option_item" and not finding this particular field. Any ideas as how to force it when only one object is found to still return it as an array?
UPDATE(05/092012)
TypeError - Symbol as array index
This error does not appear if I remove the single "option_item" from the hash or even by filtering it with a conditional statement.
As another update that was an example before, here is the code:
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
Example data(abbreviated):
{:"@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"},
Upvotes: 0
Views: 214
Reputation: 27747
Krista's example will work if there is only one option_item, but not if there's more. I'd add flatten and adjust it to:
[sub_area_option_item[:items][:option_item]].flatten.each do |option_item|
option_item[:name]
end
the [] around it makes sure it's an array. the flatten makes sure that if it already was an array, that you remove the extra layer of [] eg:
['a'].flatten
=> ["a"]
[['a','b','c',]].flatten
=> ["a", "b", "c"]
Upvotes: 2
Reputation: 915
As far as I can tell, the second part of your loop should be the problem - given your source code and the sample data
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
Note that line 01 would end up accessing location_option_item
which in your sample above is:
: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 .......
Notice that location_option_item
is the key, which has for value an array.
Thus, my guess is that this line is the problem (02): location_option_item[:items]
Since location_option_item is an array, you cannot access the :items
symbol from it.
If you wanted to get items
it would be something more like:
location_option_item[1][:items]
Upvotes: 2