-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
-Paginator module is responsible for calculating and rendering a pagination bar based on the passed parameters. -Added rspec for Paginator.
- Loading branch information
Showing
2 changed files
with
204 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
module Utilities | ||
module Paginator | ||
ELLIPSES = '...'.freeze | ||
OFFSET = 1 | ||
FIRST_PAGE = 1 | ||
DIVIDER = 2 | ||
|
||
def items_to_display(model:, items_per_page: 5, current_page: 1) | ||
@items_per_page = items_per_page | ||
@current_page = current_page | ||
@number_of_items = model.count | ||
@last_page = (@number_of_items.to_f / @items_per_page).ceil | ||
model.offset(items_per_page * (@current_page - OFFSET)) | ||
.limit(items_per_page) | ||
end | ||
|
||
def paginator(max_page_blocks: 7) | ||
render partial: 'shared/paginator', | ||
locals: { blocks: pages_to_display(@current_page, | ||
max_page_blocks, | ||
@last_page), | ||
current_page: @current_page, | ||
previous_link_css_class: previous_link_css_class, | ||
next_link_css_class: next_link_css_class, | ||
last_page: @last_page } | ||
end | ||
|
||
def page_item_css_class(page, current_page) | ||
if page == current_page | ||
'page-item active' | ||
elsif page.to_s == ELLIPSES | ||
'page-item disabled' | ||
end | ||
end | ||
|
||
private | ||
|
||
def previous_link_css_class | ||
@current_page == FIRST_PAGE ? 'page-item disabled' : 'page-item' | ||
end | ||
|
||
def next_link_css_class | ||
@current_page == @last_page ? 'page-item disabled' : 'page-item' | ||
end | ||
|
||
def pages_to_display(current_page, max_page_blocks, number_of_pages) | ||
if all_pages_fit?(number_of_pages, max_page_blocks) | ||
complete_pagination(number_of_pages) | ||
elsif current_page_at_the_beginning?(current_page, max_page_blocks) | ||
beginning_pagination(max_page_blocks) | ||
elsif current_page_at_the_end?(current_page, number_of_pages, | ||
max_page_blocks) | ||
end_pagination(max_page_blocks, number_of_pages) | ||
else | ||
general_pagination(current_page, max_page_blocks) | ||
end | ||
end | ||
|
||
def all_pages_fit?(number_of_pages, max_page_blocks) | ||
number_of_pages < max_page_blocks | ||
end | ||
|
||
def current_page_at_the_beginning?(current_page, max_page_blocks) | ||
current_page <= (max_page_blocks / DIVIDER) | ||
end | ||
|
||
def current_page_at_the_end?(current_page, number_of_pages, max_page_blocks) | ||
current_page > (number_of_pages - (max_page_blocks / DIVIDER)) | ||
end | ||
|
||
def general_pagination(current_page, max_page_blocks) | ||
if max_page_blocks == 1 | ||
[current_page] | ||
elsif max_page_blocks == 2 | ||
[current_page, ELLIPSES] | ||
elsif max_page_blocks.odd? | ||
odd_pages(current_page, max_page_blocks) | ||
else | ||
even_pages(current_page, max_page_blocks) | ||
end | ||
end | ||
|
||
def beginning_pagination(max_page_blocks) | ||
start = FIRST_PAGE | ||
finish = max_page_blocks - OFFSET | ||
[*(start..finish), ELLIPSES] | ||
end | ||
|
||
def end_pagination(max_page_blocks, number_of_pages) | ||
start = number_of_pages - max_page_blocks + OFFSET * 2 | ||
finish = number_of_pages | ||
[ELLIPSES, *(start..finish)] | ||
end | ||
|
||
def complete_pagination(last_page) | ||
[*FIRST_PAGE..last_page] | ||
end | ||
|
||
def odd_pages(current_page, max_page_blocks) | ||
start = (current_page - (max_page_blocks - OFFSET) / DIVIDER) + OFFSET | ||
finish = (current_page + (max_page_blocks - OFFSET) / DIVIDER) - OFFSET | ||
[ELLIPSES, *(start..finish), ELLIPSES] | ||
end | ||
|
||
def even_pages(current_page, max_page_blocks) | ||
start = (current_page - (max_page_blocks - OFFSET) / DIVIDER) + OFFSET | ||
finish = (current_page + (max_page_blocks / DIVIDER)) - OFFSET | ||
[ELLIPSES, *(start..finish), ELLIPSES] | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
require 'rails_helper' | ||
|
||
RSpec.describe Utilities::Paginator, type: :module do | ||
let!(:paginator) { Class.new { extend Utilities::Paginator } } | ||
|
||
describe('#pages_to_display') do | ||
subject(:pages_to_display) do | ||
paginator.send(:pages_to_display, | ||
current_page, | ||
maximum_page_blocks, | ||
number_of_pages) | ||
end | ||
|
||
context 'All pages fit within the pagination list' do | ||
let(:maximum_page_blocks) { 7 } | ||
let(:current_page) { 1 } | ||
let(:number_of_pages) { 5 } | ||
let(:expected_range_of_pages) { [1, 2, 3, 4, 5] } | ||
|
||
it 'displays correct range of pages' do | ||
expect(pages_to_display).to eq expected_range_of_pages | ||
end | ||
end | ||
|
||
context 'Current page is in the beginning and there are more pages towards the end of the pagination list' do | ||
let(:maximum_page_blocks) { 7 } | ||
let(:current_page) { 3 } | ||
let(:number_of_pages) { 11 } | ||
let(:expected_range_of_pages) { [1, 2, 3, 4, 5, 6, '...'] } | ||
|
||
it 'displays correct range of pages' do | ||
expect(pages_to_display).to eq expected_range_of_pages | ||
end | ||
end | ||
|
||
context 'Current page is at the end and there are more pages towards the beginning of the pagination list' do | ||
let(:maximum_page_blocks) { 7 } | ||
let(:current_page) { 9 } | ||
let(:number_of_pages) { 11 } | ||
let(:expected_range_of_pages) { ['...', 6, 7, 8, 9, 10, 11] } | ||
|
||
it 'displays correct range of pages' do | ||
expect(pages_to_display).to eq expected_range_of_pages | ||
end | ||
end | ||
|
||
context 'Current page is in the middle and there are more pages towards the beginning and the end of the pagination list' do | ||
context 'Maximum number of page blocks is 1' do | ||
let(:maximum_page_blocks) { 1 } | ||
let(:current_page) { 5 } | ||
let(:number_of_pages) { 11 } | ||
let(:expected_range_of_pages) { [5] } | ||
|
||
it 'displays correct range of pages' do | ||
expect(pages_to_display).to eq expected_range_of_pages | ||
end | ||
end | ||
|
||
context 'Maximum number of page blocks is 2' do | ||
let(:maximum_page_blocks) { 2 } | ||
let(:current_page) { 6 } | ||
let(:number_of_pages) { 11 } | ||
let(:expected_range_of_pages) { [6, '...'] } | ||
|
||
it 'displays correct range of pages' do | ||
expect(pages_to_display).to eq expected_range_of_pages | ||
end | ||
end | ||
|
||
context 'Maximum number of page blocks is odd' do | ||
let(:maximum_page_blocks) { 7 } | ||
let(:current_page) { 5 } | ||
let(:number_of_pages) { 11 } | ||
let(:expected_range_of_pages) { ['...', 3, 4, 5, 6, 7, '...'] } | ||
|
||
it 'displays correct range of pages' do | ||
expect(pages_to_display).to eq expected_range_of_pages | ||
end | ||
end | ||
|
||
context 'Maximum number of page blocks is even' do | ||
let(:maximum_page_blocks) { 6 } | ||
let(:current_page) { 5 } | ||
let(:number_of_pages) { 11 } | ||
let(:expected_range_of_pages) { ['...', 4, 5, 6, 7, '...'] } | ||
|
||
it 'displays correct range of pages' do | ||
expect(pages_to_display).to eq expected_range_of_pages | ||
end | ||
end | ||
end | ||
end | ||
end |