Skip to content

Commit

Permalink
Merge pull request #87 from phantomphildius/page-count
Browse files Browse the repository at this point in the history
Add page_count when using Paginators
  • Loading branch information
tiagopog authored Apr 21, 2018
2 parents 437319d + dd817cb commit 23f7af7
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 0 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,9 @@ JSONAPI.configure do |config|
config.top_level_meta_include_record_count = true
config.top_level_meta_record_count_key = :record_count

config.top_level_meta_include_page_count = true
config.top_level_meta_page_count_key = :page_count

config.use_text_errors = false

config.exception_class_whitelist = []
Expand Down
4 changes: 4 additions & 0 deletions lib/jsonapi/utils/response/formatters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@ def result_options(records, options)
if JSONAPI.configuration.top_level_meta_include_record_count
data[:record_count] = record_count_for(records, options)
end

if JSONAPI.configuration.top_level_meta_include_page_count
data[:page_count] = page_count_for(data[:record_count])
end
end
end

Expand Down
17 changes: 17 additions & 0 deletions lib/jsonapi/utils/support/pagination.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,23 @@ def count_records(records, options)
end
end

# Count pages in order to build a proper pagination and to fill up the "page_count" response's member.
#
# @param record_count [Integer] number of records
# e.g.: 42
#
# @return [Integer]
# e.g 5
#
# @api private
def page_count_for(record_count)
return 0 if record_count.to_i < 1

size = (page_params['size'] || page_params['limit']).to_i
size = JSONAPI.configuration.default_page_size unless size.nonzero?
(record_count.to_f / size).ceil
end

# Count records from the datatase applying the given request filters
# and skipping things like eager loading, grouping and sorting.
#
Expand Down
4 changes: 4 additions & 0 deletions spec/controllers/posts_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
expect(data.size).to eq(2)
expect(response).to have_meta_record_count(4)

expect(json.dig('meta', 'page_count')).to be(2)
expect(json.dig('links', 'first')).to be_present
expect(json.dig('links', 'next')).to be_present
expect(json.dig('links', 'last')).to be_present
Expand All @@ -109,6 +110,7 @@
expect(data.size).to eq(1)
expect(response).to have_meta_record_count(4)

expect(json.dig('meta', 'page_count')).to be(4)
expect(json.dig('links', 'first')).to be_present
expect(json.dig('links', 'prev')).to be_present
expect(json.dig('links', 'next')).to be_present
Expand All @@ -126,6 +128,7 @@

expect(data.size).to eq(1)

expect(json.dig('meta', 'page_count')).to be(4)
expect(json.dig('links', 'first')).to be_present
expect(json.dig('links', 'prev')).to be_present
expect(json.dig('links', 'next')).not_to be_present
Expand All @@ -142,6 +145,7 @@
expect(subject).to have_http_status :ok
expect(subject).to have_meta_record_count(4)
expect(data.size).to be <= JSONAPI.configuration.default_page_size
expect(json.dig('meta', 'page_count')).to be(1)
end
end
end
Expand Down
13 changes: 13 additions & 0 deletions spec/controllers/users_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
expect(data.size).to eq(2)
expect(response).to have_meta_record_count(3)

expect(json.dig('meta', 'page_count')).to eq(2)
expect(json.dig('links', 'first')).to be_present
expect(json.dig('links', 'next')).to be_present
expect(json.dig('links', 'last')).to be_present
Expand All @@ -128,6 +129,7 @@
expect(data.size).to eq(1)
expect(response).to have_meta_record_count(User.count)

expect(json.dig('meta', 'page_count')).to eq(3)
expect(json.dig('links', 'first')).to be_present
expect(json.dig('links', 'prev')).to be_present
expect(json.dig('links', 'next')).to be_present
Expand All @@ -144,6 +146,7 @@
expect(data.size).to eq(1)
expect(response).to have_meta_record_count(User.count)

expect(json.dig('meta', 'page_count')).to eq(3)
expect(json.dig('links', 'first')).to be_present
expect(json.dig('links', 'prev')).to be_present
expect(json.dig('links', 'last')).to be_present
Expand All @@ -162,6 +165,7 @@
expect(data.size).to eq(1)
expect(response).to have_meta_record_count(count)

expect(json.dig('meta', 'page_count')).to eq(1)
expect(data.dig(0, 'attributes', 'full_name')).to eq(user.full_name)
end
end
Expand All @@ -172,6 +176,7 @@
expect(response).to have_http_status :ok
expect(data.size).to be <= JSONAPI.configuration.default_page_size
expect(response).to have_meta_record_count(User.count)
expect(json.dig('meta', 'page_count')).to eq(1)
end
end
end
Expand All @@ -190,6 +195,7 @@
expect(data.size).to eq(2)
expect(response).to have_meta_record_count(User.count)

expect(json.dig('meta', 'page_count')).to eq(2)
expect(json.dig('links', 'first')).to be_present
expect(json.dig('links', 'next')).to be_present
expect(json.dig('links', 'last')).to be_present
Expand All @@ -205,6 +211,7 @@
expect(data.size).to eq(1)
expect(response).to have_meta_record_count(User.count)

expect(json.dig('meta', 'page_count')).to eq(3)
expect(json.dig('links', 'first')).to be_present
expect(json.dig('links', 'prev')).to be_present
expect(json.dig('links', 'next')).to be_present
Expand All @@ -221,6 +228,7 @@
expect(data.size).to eq(1)
expect(response).to have_meta_record_count(User.count)

expect(json.dig('meta', 'page_count')).to eq(3)
expect(json.dig('links', 'first')).to be_present
expect(json.dig('links', 'prev')).to be_present
expect(json.dig('links', 'last')).to be_present
Expand All @@ -233,6 +241,7 @@
expect(response).to have_http_status :ok
expect(data.size).to be <= JSONAPI.configuration.default_page_size
expect(response).to have_meta_record_count(User.count)
expect(json.dig('meta', 'page_count')).to eq(1)
end
end
end
Expand All @@ -251,6 +260,7 @@
expect(data.size).to eq(2)
expect(response).to have_meta_record_count(User.count)

expect(json.dig('meta', 'page_count')).to eq(2)
expect(json.dig('links', 'first')).to be_present
expect(json.dig('links', 'next')).to be_present
expect(json.dig('links', 'last')).to be_present
Expand All @@ -266,6 +276,7 @@
expect(data.size).to eq(1)
expect(response).to have_meta_record_count(User.count)

expect(json.dig('meta', 'page_count')).to eq(3)
expect(json.dig('links', 'first')).to be_present
expect(json.dig('links', 'prev')).to be_present
expect(json.dig('links', 'next')).to be_present
Expand All @@ -282,6 +293,7 @@
expect(data.size).to eq(1)
expect(response).to have_meta_record_count(User.count)

expect(json.dig('meta', 'page_count')).to eq(3)
expect(json.dig('links', 'first')).to be_present
expect(json.dig('links', 'prev')).to be_present
expect(json.dig('links', 'last')).to be_present
Expand All @@ -294,6 +306,7 @@
expect(response).to have_http_status :ok
expect(data.size).to be <= JSONAPI.configuration.default_page_size
expect(response).to have_meta_record_count(User.count)
expect(json.dig('meta', 'page_count')).to eq(1)
end
end
end
Expand Down
91 changes: 91 additions & 0 deletions spec/features/page_count_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
require 'rails_helper'

##
# Configs
##

# Resource
class PageCountTestResource < JSONAPI::Resource; end

# Controller
class PageCountTestController < BaseController
def index
jsonapi_render json: User.all, options: { resource: UserResource }
end
end

# Routes
def TestApp.draw_page_count_test_routes
JSONAPI.configuration.json_key_format = :underscored_key

TestApp.routes.draw do
controller :page_count_test do
get :index
end
end
end

##
# Feature Tests
##


describe PageCountTestController, type: :controller do
include_context 'JSON API headers'

before(:all) do
TestApp.draw_page_count_test_routes
FactoryGirl.create_list(:user, 3, :with_posts)
end

describe 'page count with a paged paginator' do
it 'returns the correct count' do
JSONAPI.configuration.default_paginator = :paged

get :index, params: { page: { size: 2, number: 1 } }

expect(json.dig('meta', 'page_count')).to eq(2)
end
end

describe 'page count with an offset paginator' do
it 'returns the correct count' do
JSONAPI.configuration.default_paginator = :offset

get :index, params: { page: { limit: 2, offset: 1 } }

expect(json.dig('meta', 'page_count')).to eq(2)
end
end

describe 'page count with a custom paginator' do
it 'returns the correct count' do
JSONAPI.configuration.default_paginator = :custom_offset

get :index, params: { page: { limit: 2, offset: 1 } }

expect(json.dig('meta', 'page_count')).to eq(2)
end
end

describe 'using default limit param' do
it 'returns the correct count' do
JSONAPI.configuration.default_paginator = :offset

get :index, params: { page: { offset: 1 } }

expect(json.dig('meta', 'page_count')).to eq(1)
end
end

describe 'using a custom page_count key' do
it 'returns the count with the correct key' do
JSONAPI.configuration.default_paginator = :paged
JSONAPI.configuration.top_level_meta_page_count_key = :total_pages

get :index, params: { page: { limit: 2, offset: 1 } }

expect(json.dig('meta', 'total_pages')).to eq(2)
end
end
end
37 changes: 37 additions & 0 deletions spec/jsonapi/utils/support/pagination_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,43 @@
end
end

describe '#count_pages_for' do
shared_examples_for 'counting pages' do
it 'returns the correct page count' do
allow(subject).to receive(:page_params).and_return(page_params)
expect(subject.send(:page_count_for, record_count)).to eq(page_count)
end
end

context 'with paged paginator' do
let(:record_count) { 10 }
let(:page_count) { 2 }
let(:page_params) { { 'size' => 5 } }
it_behaves_like 'counting pages'
end

context 'with offset paginator' do
let(:record_count) { 10 }
let(:page_count) { 2 }
let(:page_params) { { 'limit' => 5 } }
it_behaves_like 'counting pages'
end

context 'with 0 records' do
let(:record_count) { 0 }
let(:page_count) { 0 }
let(:page_params) { {} }
it_behaves_like 'counting pages'
end

context 'with no limit param' do
let(:record_count) { 10 }
let(:page_count) { 1 }
let(:page_params) { {} }
it_behaves_like 'counting pages'
end
end

describe '#count_records_from_database' do
shared_examples_for 'skipping eager load SQL when counting records' do
it 'skips any eager load for the SQL count query (default)' do
Expand Down
3 changes: 3 additions & 0 deletions spec/test_app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

config.top_level_meta_include_record_count = true
config.top_level_meta_record_count_key = :record_count

config.top_level_meta_include_page_count = true
config.top_level_meta_page_count_key = :page_count
end

##
Expand Down

0 comments on commit 23f7af7

Please sign in to comment.