Skip to content
Snippets Groups Projects
Commit 0eef8276 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets
Browse files

Merge branch 'add-pagination-headers-to-api' into 'master'

Add pagination headers to already paginated API resources

Following #3045, I've added pagination headers using already available Kaminari methods.

## Pagination headers in action

![Screen_Shot_2016-01-14_at_12.14.53](/uploads/88807f754dd9aafbb24da85f6bdf9521/Screen_Shot_2016-01-14_at_12.14.53.png)

---

I've also added a shared example to test paginated API resources.

A possible next step would be to paginate all the API resources that return an array.

See merge request !2426
parents 0430c00c 1b08cd81
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -4,6 +4,7 @@ v 8.5.0 (unreleased)
- Remove gray background from layout in UI
 
v 8.4.0 (unreleased)
- Add pagination headers to already paginated API resources
- Improve the consistency of commit titles, branch names, tag names, issue/MR titles, on their respective project pages
- Autocomplete data is now always loaded, instead of when focusing a comment text area (Yorick Peterse)
- Improved performance of finding issues for an entire group (Yorick Peterse)
Loading
Loading
Loading
Loading
@@ -97,11 +97,9 @@ module API
end
 
def paginate(relation)
per_page = params[:per_page].to_i
paginated = relation.page(params[:page]).per(per_page)
add_pagination_headers(paginated, per_page)
paginated
relation.page(params[:page]).per(params[:per_page].to_i).tap do |data|
add_pagination_headers(data)
end
end
 
def authenticate!
Loading
Loading
@@ -329,16 +327,26 @@ module API
 
private
 
def add_pagination_headers(paginated, per_page)
def add_pagination_headers(paginated_data)
header 'X-Total', paginated_data.total_count.to_s
header 'X-Total-Pages', paginated_data.total_pages.to_s
header 'X-Per-Page', paginated_data.limit_value.to_s
header 'X-Page', paginated_data.current_page.to_s
header 'X-Next-Page', paginated_data.next_page.to_s
header 'X-Prev-Page', paginated_data.prev_page.to_s
header 'Link', pagination_links(paginated_data)
end
def pagination_links(paginated_data)
request_url = request.url.split('?').first
 
links = []
links << %(<#{request_url}?page=#{paginated.current_page - 1}&per_page=#{per_page}>; rel="prev") unless paginated.first_page?
links << %(<#{request_url}?page=#{paginated.current_page + 1}&per_page=#{per_page}>; rel="next") unless paginated.last_page?
links << %(<#{request_url}?page=1&per_page=#{per_page}>; rel="first")
links << %(<#{request_url}?page=#{paginated.total_pages}&per_page=#{per_page}>; rel="last")
links << %(<#{request_url}?page=#{paginated_data.current_page - 1}&per_page=#{paginated_data.limit_value}>; rel="prev") unless paginated_data.first_page?
links << %(<#{request_url}?page=#{paginated_data.current_page + 1}&per_page=#{paginated_data.limit_value}>; rel="next") unless paginated_data.last_page?
links << %(<#{request_url}?page=1&per_page=#{paginated_data.limit_value}>; rel="first")
links << %(<#{request_url}?page=#{paginated_data.total_pages}&per_page=#{paginated_data.limit_value}>; rel="last")
 
header 'Link', links.join(', ')
links.join(', ')
end
 
def abilities
Loading
Loading
require 'spec_helper'
 
describe API::API, api: true do
describe API::CommitStatus, api: true do
include ApiHelpers
let(:user) { create(:user) }
let(:user2) { create(:user) }
Loading
Loading
@@ -12,6 +12,10 @@ describe API::API, api: true do
let(:commit_status) { create(:commit_status, commit: ci_commit) }
 
describe "GET /projects/:id/repository/commits/:sha/statuses" do
it_behaves_like 'a paginated resources' do
let(:request) { get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses", user) }
end
context "reporter user" do
let(:statuses_id) { json_response.map { |status| status['id'] } }
 
Loading
Loading
Loading
Loading
@@ -32,6 +32,10 @@ describe API::API, api: true do
before { project.team << [user, :reporter] }
 
describe "GET /projects/:id/noteable/:noteable_id/notes" do
it_behaves_like 'a paginated resources' do
let(:request) { get api("/projects/#{project.id}/issues/#{issue.id}/notes", user) }
end
context "when noteable is an Issue" do
it "should return an array of issue notes" do
get api("/projects/#{project.id}/issues/#{issue.id}/notes", user)
Loading
Loading
# Specs for paginated resources.
#
# Requires an API request:
# let(:request) { get api("/projects/#{project.id}/repository/branches", user) }
shared_examples 'a paginated resources' do
before do
# Fires the request
request
end
it 'has pagination headers' do
expect(response.headers).to include('X-Total')
expect(response.headers).to include('X-Total-Pages')
expect(response.headers).to include('X-Per-Page')
expect(response.headers).to include('X-Page')
expect(response.headers).to include('X-Next-Page')
expect(response.headers).to include('X-Prev-Page')
expect(response.headers).to include('Link')
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment