从API获取所有页面

时间:2016-03-07 23:17:45

标签: ruby-on-rails ruby

这是我挣扎的事情,或者每当我这样做时,它似乎都很混乱。 我会以一种非常通用的方式提出这个问题,因为这不是我真正试图解决的问题。

我有一个API,我想从中消耗一些数据,例如通过:

def get_api_results(page)
  results = HTTParty.get("api.api.com?page=#{page}")
end

当我打电话给它时,我可以检索一个总数。

results["total"] = 237

API限制了我在一次通话中可以检索的记录数量,比如说20个。所以我需要多次调用它。

我想做类似以下的事情,最好把它分成几块,这样我就可以使用像delayed_job..etc这样的东西

def get_all_api_pages
  results = get_api_results(1)
  total = get_api_results(1)["total"]

  until page*20 > total do |p|
    results += get_api_results(p)
  end
end

每当我尝试解决这个问题时,我总是觉得我在写垃圾(而且我试图以多种方式解决它)。 例如,上面的内容让我受到API错误的支配,如果我在任何时候遇到错误,它会敲掉我收集的所有结果。

想知道是否只有一种通常良好,干净的方式来处理这种情况。

1 个答案:

答案 0 :(得分:1)

我认为你没有那么干净......因为你只有在调用API后才收到总数。 你有没有尝试为此建立自己的枚举。它封装了丑陋的部分。这里有一些带有"模拟"的示例代码。 API:

class AllRecords
  PER_PAGE = 50

  def each
    return enum_for(:each) unless block_given?
    current_page = 0
    total = nil
    while total.nil? || current_page * PER_PAGE < total
      current_page += 1
      page = load_page(current_page)
      total = page[:total]
      page[:items].each do |item|
        yield(item)
      end
    end
  end

  private

  def load_page(page)
    if page == 5
      {items: Array.new(37) { rand(100) }, total: 237}
    else
      {items: Array.new(50) { rand(100) }, total: 237}
    end
  end
end

AllRecords.new.each.each_with_index do |item, index|
  p index
end

你可以肯定地清理一下,但我认为这很好,因为它不会先收集所有物品。