I wanted to write a functional solution which would closely resemble the task you want to achieve.
I'd say that your solution comes down to this:
For all page numbers from 1 on, you get the corresponding list of items; Take lists while they are not empty, and join them into a single array.
Sounds ok?
Now let's try to translate this, almost literally, to Ruby:
(1..Float::INFINITY). # For all page numbers from 1 on map{|page| get_page_items page}. # get the corresponding list of items take_while{|items| !items.empty?}. # Take lists while they are not empty inject(&:+) # and join them into a single array.
Unfortunately, the above code won't work right away, as Ruby's map is not lazy, i.e. it would try to evaluate on all members of the infinite range first, before our take_while had the chance to peek at the values.
However, implementing a lazy map is not that hard at all, and it could be useful for other stuff. Here's one straightforward implementation, along with nice examples in the blog post.
module Enumerable def lazy_map Enumerator.new do |yielder| self.each do |value| yielder.yield(yield value) end end end end
Along with a mockup of your actual HTTP call, which returns arrays of random length between 0 and 4:
# This simulates actual HTTP call, sometimes returning an empty array def get_page_items page (1..rand(5)).to_a end
Now we have all the needed parts to solve our problem easily:
(1..Float::INFINITY). # For all page numbers from 1 on lazy_map{|page| get_page_items page}. # get the corresponding list of items take_while{|items| !items.empty?}. # Take lists while they are not empty inject(&:+) # and join them into a single array. #=> [1, 1, 2, 3, 1]
get_page_itemsreturn an empty array whenpageis out of bounds? I'm inferring from the structure that this is the logic.