Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support defining paginator on resource #92

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/jsonapi/utils/response/formatters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ def get_source_relationship(options)
# @api private
def result_options(records, options)
{}.tap do |data|
if JSONAPI.configuration.default_paginator != :none &&
if apply_pagination?(options) &&
JSONAPI.configuration.top_level_links_include_pagination
data[:pagination_params] = pagination_params(records, options)
end
Expand All @@ -273,7 +273,7 @@ def result_options(records, options)
end

if JSONAPI.configuration.top_level_meta_include_page_count
data[:page_count] = page_count_for(data[:record_count])
data[:page_count] = apply_pagination?(options) ? page_count_for(data[:record_count]) : 1
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If JSONAPI.configuration.top_level_meta_include_page_count is true but apply_pagination? is false, then page count should always equal 1

end
end
end
Expand Down
20 changes: 12 additions & 8 deletions lib/jsonapi/utils/support/pagination.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,21 @@ def record_count_for(records, options)
#
# @api private
def paginator
@paginator ||= paginator_klass.new(page_params)
@paginator ||= begin
paginator_klass = "#{resource_paginator_name}_paginator".classify.constantize
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed this from being its own method to living inside paginator because a) it's not used anywhere else and b) I thought it might confusing to have paginator, paginator_klass, and resource_paginator_name methods.

paginator_klass.new(page_params)
end
end

# Return the paginator class to be used in the response's pagination.
# Return the name of the resource's paginator.
# Points to default paginator unless paginator explicitly set on resource.
#
# @return [Paginator]
# @return [Symbol]
# e.g.: :paged or :offset
#
# @api private
def paginator_klass
"#{JSONAPI.configuration.default_paginator}_paginator".classify.constantize
def resource_paginator_name
@resource_paginator_name ||= @request.resource_klass._paginator
end

# Check whether pagination should be applied to the response.
Expand All @@ -80,8 +85,7 @@ def paginator_klass
#
# @api private
def apply_pagination?(options)
JSONAPI.configuration.default_paginator != :none &&
(options[:paginate].nil? || options[:paginate])
resource_paginator_name != :none && options[:paginate] != false
end

# Creates an instance of ActionController::Parameters for page params.
Expand Down Expand Up @@ -121,7 +125,7 @@ def paginate_with(kind)
#
# @api private
def pagination_range
case JSONAPI.configuration.default_paginator
case resource_paginator_name
when :paged
number = page_params['number'].to_i.nonzero? || 1
size = page_params['size'].to_i.nonzero? || JSONAPI.configuration.default_page_size
Expand Down
4 changes: 2 additions & 2 deletions spec/controllers/posts_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@
end
end

context 'when using custom global paginator' do
context 'when using custom paginator' do
before(:all) do
JSONAPI.configuration.default_paginator = :custom_offset
PostResource.paginator :custom_offset
end

let(:params) { { user_id: parent_id, page: { offset: offset, limit: limit } } }
Expand Down
26 changes: 22 additions & 4 deletions spec/controllers/users_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
context 'with "page"' do
context 'when using "paged" paginator' do
before(:all) do
JSONAPI.configuration.default_paginator = :paged
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to change the resource paginator instead of the default config because of the way @request.resource_klass._paginator works in Pagination. If @paginator has not been set on the resource, then it is set to the default config paginator. That's all good for the first set of paginator tests, but when it moves on to the next ones and updates the default paginator setting, @paginator for UserResource is still set to what it was previously.

So, in the course of running the "paged" tests, UserResource._paginator gets set to :paged, even if you never updated the UserResource directly & changed the default paginator setting. When it gets to the "offset" tests and you update the default paginator to "offset", then you'll get an error because UserResource._paginator is still set as :paged.

Basically, this change is solving an issue with the tests themselves, not an issue being raised by the code.

UserResource.paginator :paged
end

context 'at the first page' do
Expand Down Expand Up @@ -183,7 +183,7 @@

context 'when using "offset" paginator' do
before(:all) do
JSONAPI.configuration.default_paginator = :offset
UserResource.paginator :offset
end

context 'at the first page' do
Expand Down Expand Up @@ -246,9 +246,9 @@
end
end

context 'when using custom global paginator' do
context 'when using custom paginator' do
before(:all) do
JSONAPI.configuration.default_paginator = :custom_offset
UserResource.paginator :custom_offset
end

context 'at the first page' do
Expand Down Expand Up @@ -310,6 +310,24 @@
end
end
end

context 'without pagination' do
before(:all) do
UserResource.paginator :none
end

it 'returns all results without pagination links' do
get :index, params: { page: { offset: 0, limit: 2 } }

expect(response).to have_http_status :ok
expect(response).to have_primary_data('users')
expect(data.size).to eq(User.count)
expect(response).to have_meta_record_count(User.count)

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

context 'with "sort"' do
Expand Down
37 changes: 36 additions & 1 deletion spec/jsonapi/utils/support/pagination_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
end
end

describe '#count_pages_for' do
describe '#page_count_for' do
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed this to match the corresponding method name

shared_examples_for 'counting pages' do
it 'returns the correct page count' do
allow(subject).to receive(:page_params).and_return(page_params)
Expand Down Expand Up @@ -164,4 +164,39 @@
expect(subject.send(:distinct_count_sql, records)).to eq('DISTINCT foos.id')
end
end

describe '#apply_pagination?' do
shared_examples_for 'checking pagination' do
it 'returns whether to apply pagination' do
allow(subject).to receive(:resource_paginator_name).and_return(paginator)
expect(subject.send(:apply_pagination?, options)).to eq(apply)
end
end

context 'with paged paginator' do
let(:paginator) { :paged }
let(:apply) { true }
it_behaves_like 'checking pagination'
end

context 'without paginator' do
let(:paginator) { :none }
let(:apply) { false }
it_behaves_like 'checking pagination'
end

context 'when options[:paginate] is false' do
let(:paginator) { :paged }
let(:options) { { paginate: false } }
let(:apply) { false }
it_behaves_like 'checking pagination'
end

context 'when options[:paginate] is nil' do
let(:paginator) { :paged }
let(:options) { { paginate: nil } }
let(:apply) { true }
it_behaves_like 'checking pagination'
end
end
end
2 changes: 1 addition & 1 deletion spec/support/controllers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def index
jsonapi_render json: @user.posts, options: { count: 100 }
end

# GET /users/:user_id//index_with_hash
# GET /users/:user_id/index_with_hash
def index_with_hash
@posts = { data: [
{ id: 1, title: 'Lorem Ipsum', body: 'Body 4' },
Expand Down