Reputation: 91
I am trying to create a new hash out of object attributes from an array of objects. I am using the Amazon API via the ruby aaws gem, and I am having trouble figuring out how to loop through the array that the API returns so that it will only the attributes and not the entire array. When i run the code below, it returns the entire array.
def self.amazon(search)
keywords = "#{search}"
resp = Amazon::AWS.item_search('Books', { 'Title' => keywords })
items = resp.item_search_response[0].items[0].item
items.each do |attribs|
a = attribs.item_attributes
@results = []
@results << {:label => "#{a.title.to_s[0,85] unless a.title.nil?}",
:value => "#{a.title.to_s unless a.title.nil?}",
:img => "#{attribs.medium_image.url.to_s unless attribs.medium_image.url.nil?}"""
}
end
end
I need to modify the loop, but I am not sure exactly where I am wrong.
Upvotes: 0
Views: 3325
Reputation: 6872
The each
method returns the array it was operating on -- in this case, items
. It looks like you want to return @results, instead. You also seem to be initializing @results back to []
on each pass. Moving the @results = []
outside the loop and adding an explicit return @results
or (more idiomatically) just @results
after your loop should do the trick.
You might want to look in to the map
method, though. With it, you could just do this:
@results = items.map do |attribs|
a = attribs.item_attributes
{:label => "#{a.title.to_s[0,85] unless a.title.nil?}",
:value => "#{a.title.to_s unless a.title.nil?}",
:img => "#{attribs.medium_image.url.to_s unless attribs.medium_image.url.nil?}"
}
end
That should set your variable and also return it, as long as it's the last statement in the method. (I'm assuming you need @results to be set later - if you don't, you can leave it out entirely.)
Upvotes: 2
Reputation: 221
You can avoid the creation of a @results variable which you need to return explicitly by using the Enumerable#map method, something like this:
items.map do |attribs|
a = attribs.item_attributes
{:label => "#{a.title.to_s[0,85] unless a.title.nil?}",
:value => "#{a.title.to_s unless a.title.nil?}",
:img => "#{attribs.medium_image.url.to_s unless attribs.medium_image.url.nil?}"
}
end
Enumerable#map returns an array of the return values of running the supplied block on each item in the receiving array. So if the intention in your original method is to return @results, you might be better off using map.
Incidentally, even if you put 'return @results' at the end of the method as it stands, it will only give the attributes computed in the last iteration of the loop, since you reset @results to [] each time the block is called. You could either avoid this by initializing @results to [] before the loop or by avoiding it entirely using map.
Upvotes: 0