#1136·kaminari

Unable to display pagination for array without known total_count returned from API

Author: bogdanCreated Oct 19, 2024Updated Oct 19, 2024

I need to display pagination a collection returned from API. The API doesn't return total_count, so I can't relay on it to calculate current page. It looks like paginate_array can not deal with the situation when:

  • Passed collection is already paginated by API
  • total_count is unknown

Passing total_count: nil causes passed array to be paginated again and returns an empty array. My best guess how it should work is below where you would manually calculate limit and offset based on page and per_page and pass total_count as always having one more page.

ruby
   PER_PAGE = 10

  def fetch_github_issues(params)
    url = URI("https://api.github.com/repos/bogdan/datagrid/issues")

    params = params.compact

    url.query = URI.encode_www_form(params) unless params.empty?

    http = Net::HTTP.new(url.host, url.port)
    http.use_ssl = true

    request = Net::HTTP::Get.new(url)
    # GitHub API requires a User-Agent header
    request['User-Agent'] = 'Ruby'

    response = http.request(request)

    if response.is_a?(Net::HTTPSuccess)
      JSON.parse(response.body)
    else
      raise "Github API is down."
    end
  end

  def fetch(params = {})
    page = params[:page] || 1
    Kaminari.paginate_array(
      fetch_github_issues(params),
      limit: PER_PAGE,
      offset: (page - 1) * PER_PAGE,
      total_count: PER_PAGE * (page + 1),
    )
  end

  fetch(state: 'all', filter: 'all', page: 1)

The downside of this approach is that it paginate helper can not be used but only link_to_next/previous_page instead, which is better than nothing, but the complexity of the solution is too high.