Skip to content

Commit

Permalink
Create Paginator module
Browse files Browse the repository at this point in the history
-Paginator module is responsible for calculating and rendering a
pagination bar based on the passed parameters.
-Added rspec for Paginator.
  • Loading branch information
LeonTenko committed Apr 5, 2017
1 parent ca43116 commit c30d7f4
Show file tree
Hide file tree
Showing 2 changed files with 204 additions and 0 deletions.
111 changes: 111 additions & 0 deletions lib/utilities/paginator.rb
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
93 changes: 93 additions & 0 deletions spec/modules/paginator_spec.rb
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

0 comments on commit c30d7f4

Please sign in to comment.