simply_paginate 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +48 -29
- data/examples/data_mapper_example/Gemfile +7 -0
- data/examples/data_mapper_example/test.rb +19 -0
- data/lib/simply_paginate/page.rb +19 -17
- data/lib/simply_paginate/paginator.rb +45 -8
- data/lib/simply_paginate/version.rb +1 -1
- data/spec/page_spec.rb +22 -57
- data/spec/paginator_spec.rb +59 -32
- data/spec/spec_helper.rb +10 -0
- metadata +4 -2
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# SimplyPaginate
|
2
|
-
[![Build Status](https://travis-ci.org/guiman/simply_paginate.png)](https://travis-ci.org/guiman/simply_paginate)
|
2
|
+
[![Build Status](https://travis-ci.org/guiman/simply_paginate.png)](https://travis-ci.org/guiman/simply_paginate) [![Code Climate](https://codeclimate.com/github/guiman/simply_paginate.png)](https://codeclimate.com/github/guiman/simply_paginate)
|
3
3
|
|
4
4
|
Simply paginate will do just that, give me a collection and you will be able to use a pagination logic (no extra html boilerplate or dependecies).
|
5
5
|
|
@@ -19,60 +19,79 @@ Or install it yourself as:
|
|
19
19
|
|
20
20
|
## Motivation
|
21
21
|
When dealing with pagination most known gems come bundled with lots of extra functionality I usually don't need (like html boilerplate), this is my attempt to create just the pagination logic, as simple as that.
|
22
|
+
So if you need pagiation but don't want to reinvent the wheel and keep your collections Pagination Agnostic, this is the gem you need. The only
|
23
|
+
requirement is the adoption of the popular ruby Enumerable interface.
|
22
24
|
|
23
25
|
## Usage
|
24
26
|
|
25
27
|
```ruby
|
26
28
|
require 'simply_paginate'
|
27
29
|
|
28
|
-
|
30
|
+
include SimplyPaginate
|
29
31
|
|
30
|
-
|
32
|
+
collection = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
31
33
|
|
32
|
-
|
33
|
-
SimplyPaginate::Paginator.per_page 3
|
34
|
+
pages = Paginator.new(collection, 3)
|
34
35
|
|
35
36
|
# retrieve a certain page
|
36
|
-
|
37
|
+
pages[1]
|
37
38
|
|
38
39
|
#move through the pages freely
|
39
|
-
|
40
|
-
|
40
|
+
pages[1].next
|
41
|
+
pages[1].previous
|
41
42
|
|
42
43
|
#you might want the first element on the 3rd page
|
43
|
-
|
44
|
+
pages[1].next.next.next.previous.elements[0]
|
44
45
|
|
45
46
|
#or maybe all of them
|
46
|
-
|
47
|
-
```
|
47
|
+
pages[0].next.next.next.previous.elements
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
# By default Paginator.per_page is 10
|
49
|
+
#you can also iterate the ruby way
|
50
|
+
pages.each do |page|
|
51
|
+
puts page.elements
|
52
|
+
end
|
54
53
|
|
55
|
-
|
54
|
+
#or in a more old fashion way
|
55
|
+
pages.start
|
56
56
|
|
57
|
-
|
57
|
+
while pages.next? do
|
58
|
+
puts pages.current.elements
|
59
|
+
|
60
|
+
pages.next!
|
61
|
+
end
|
58
62
|
```
|
59
63
|
|
60
|
-
##
|
64
|
+
## Changes on this branch
|
65
|
+
Well this branch introduced a better design about the relationship between pages and page, and also
|
66
|
+
an improvement on the API.
|
61
67
|
|
62
|
-
|
63
|
-
|
68
|
+
Now a Page can be used without the need of having a Paginator, and also a Paginator could be transversed
|
69
|
+
without need to access pages directly.
|
64
70
|
|
65
|
-
|
66
|
-
|
67
|
-
so when you call ```previous``` or ```next``` or ```[]```page object representing is created on that moment, thus saving memory.
|
71
|
+
```ruby
|
72
|
+
require 'simply_paginate'
|
68
73
|
|
69
|
-
|
70
|
-
also the ```pages``` has been dropped.
|
74
|
+
include SimplyPaginate
|
71
75
|
|
72
|
-
|
73
|
-
* Dropping the each_slice in order to use a more memory efficient index algorithm for paging.
|
74
|
-
* Adding more tests to the page object.
|
76
|
+
collection = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
75
77
|
|
78
|
+
# Give me the first page of the collection with a size of 3
|
79
|
+
first_page = Page.new(1, collection, 3)
|
80
|
+
|
81
|
+
first_page.elements
|
82
|
+
#=> [1, 2, 3]
|
83
|
+
first_page.next.elements
|
84
|
+
#=> [4, 5, 6]
|
85
|
+
```
|
86
|
+
##0.0.4 - Changelog:
|
87
|
+
|
88
|
+
* Redesign on relation between paginator and pages. You can use them togheter or separately.
|
89
|
+
* Improved API for Paginator, now including:
|
90
|
+
* each iteration
|
91
|
+
* next!, next?, current and start methods for manual iteration
|
92
|
+
* first and last accessors
|
93
|
+
* Test improvement
|
94
|
+
|
76
95
|
## Contributing
|
77
96
|
|
78
97
|
1. Fork it
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.require
|
3
|
+
|
4
|
+
DataMapper.setup :default, 'sqlite::memory:'
|
5
|
+
|
6
|
+
class Person
|
7
|
+
include DataMapper::Resource
|
8
|
+
|
9
|
+
property :id, Serial
|
10
|
+
property :age, String
|
11
|
+
end
|
12
|
+
|
13
|
+
DataMapper.auto_migrate!
|
14
|
+
|
15
|
+
100.times { Person.create age: rand(1..90) }
|
16
|
+
|
17
|
+
paginator = SimplyPaginate::Paginator.new(Person.all)
|
18
|
+
|
19
|
+
paginator[0].elements.all(:age.gt => 10)
|
data/lib/simply_paginate/page.rb
CHANGED
@@ -1,33 +1,35 @@
|
|
1
1
|
module SimplyPaginate
|
2
2
|
class Page
|
3
|
-
attr_reader :
|
3
|
+
attr_reader :index, :collection, :size
|
4
4
|
|
5
|
-
def initialize(
|
6
|
-
@
|
7
|
-
@
|
8
|
-
@
|
5
|
+
def initialize(page, collection, size = Paginator.per_page)
|
6
|
+
@index = page
|
7
|
+
@collection = collection
|
8
|
+
@size = size
|
9
|
+
|
10
|
+
@move_page = lambda do |number|
|
11
|
+
new_index = @index + number
|
12
|
+
Page.new(new_index, @collection, @size) unless (new_index == 0) || (new_index > (@collection.count.to_f / @size.to_f).ceil)
|
13
|
+
end
|
9
14
|
end
|
10
15
|
|
11
16
|
def next
|
12
|
-
|
13
|
-
last = first + Paginator.per_page - 1
|
14
|
-
|
15
|
-
(first >= @paginator.collection.count) ? nil : @paginator.current = Page.new(first, last, @paginator)
|
17
|
+
@move_page.call(1)
|
16
18
|
end
|
17
19
|
|
18
20
|
def previous
|
19
|
-
|
20
|
-
last = @first - 1
|
21
|
-
|
22
|
-
(first < 0) ? nil : @paginator.current = Page.new(first, last, @paginator)
|
21
|
+
@move_page.call(-1)
|
23
22
|
end
|
24
23
|
|
25
|
-
def
|
26
|
-
|
24
|
+
def elements
|
25
|
+
first = (@index - 1) * @size
|
26
|
+
last = first + size - 1
|
27
|
+
|
28
|
+
collection[first..last]
|
27
29
|
end
|
28
30
|
|
29
|
-
def
|
30
|
-
|
31
|
+
def ==(other)
|
32
|
+
(index == other.index) && (elements == other.elements) if other.respond_to?(:index) && other.respond_to?(:elements)
|
31
33
|
end
|
32
34
|
end
|
33
35
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module SimplyPaginate
|
2
|
+
FIRST_PAGE_INDEX = 1
|
3
|
+
|
2
4
|
class Paginator
|
3
5
|
attr_reader :collection
|
4
|
-
attr_accessor :current
|
5
6
|
|
6
7
|
def self.per_page=(amount_per_page)
|
7
8
|
raise NotInRangeError.new("Amount per page should be greater than 0") unless amount_per_page > 0
|
@@ -13,20 +14,56 @@ module SimplyPaginate
|
|
13
14
|
@@per_page
|
14
15
|
end
|
15
16
|
|
16
|
-
def initialize(collection)
|
17
|
+
def initialize(collection, per_page = self.class.per_page)
|
17
18
|
@collection = collection
|
18
|
-
@
|
19
|
+
@per_page = per_page
|
19
20
|
end
|
20
21
|
|
21
|
-
|
22
|
-
first = pos * @@per_page
|
23
|
-
last = first + @@per_page - 1
|
22
|
+
## Basic Operations
|
24
23
|
|
25
|
-
|
24
|
+
def first
|
25
|
+
self[FIRST_PAGE_INDEX]
|
26
|
+
end
|
27
|
+
|
28
|
+
def last
|
29
|
+
self[total_pages]
|
26
30
|
end
|
27
31
|
|
28
32
|
def total_pages
|
29
|
-
(@collection.count.to_f /
|
33
|
+
(@collection.count.to_f / @per_page.to_f).ceil
|
34
|
+
end
|
35
|
+
|
36
|
+
def [](pos)
|
37
|
+
Page.new(pos, @collection) unless pos == 0 || pos > total_pages
|
38
|
+
end
|
39
|
+
|
40
|
+
## Iteration
|
41
|
+
|
42
|
+
def next!
|
43
|
+
raise NoMethodError.new("You need to start before iterating") unless @current
|
44
|
+
@current = @current.next
|
45
|
+
end
|
46
|
+
|
47
|
+
def next?
|
48
|
+
@current != nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def start
|
52
|
+
@current = first
|
53
|
+
end
|
54
|
+
|
55
|
+
def current
|
56
|
+
@current
|
57
|
+
end
|
58
|
+
|
59
|
+
def each
|
60
|
+
start
|
61
|
+
|
62
|
+
while next? do
|
63
|
+
yield current
|
64
|
+
|
65
|
+
next!
|
66
|
+
end
|
30
67
|
end
|
31
68
|
|
32
69
|
Paginator.per_page = 10
|
data/spec/page_spec.rb
CHANGED
@@ -1,74 +1,39 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
before do
|
5
|
-
SimplyPaginate::Paginator.per_page = 5
|
3
|
+
include SimplyPaginate
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
@last_page = SimplyPaginate::Page.new(5, 9, @paginator)
|
5
|
+
describe Page do
|
6
|
+
include Helpers
|
10
7
|
|
11
|
-
|
12
|
-
def paginator
|
13
|
-
@paginator
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
it "must always have an instance of paginator" do
|
19
|
-
@first_page.paginator.wont_be_nil
|
20
|
-
@last_page.paginator.wont_be_nil
|
8
|
+
let(:first_page) { build_page 1 }
|
21
9
|
|
22
|
-
|
23
|
-
@first_page.next.previous.paginator.wont_be_nil
|
24
|
-
end
|
10
|
+
let(:second_page) { build_page 2 }
|
25
11
|
|
26
|
-
|
27
|
-
@first_page.elements.must_equal [1, 2, 3, 4, 5]
|
28
|
-
@last_page.elements.must_equal [6, 7, 8, 9, 10]
|
12
|
+
let(:last_page) { build_page 4 }
|
29
13
|
|
30
|
-
|
31
|
-
|
14
|
+
it "must represent a specific page on a collection" do
|
15
|
+
first_page.elements.must_equal [1, 2, 3]
|
16
|
+
first_page.index.must_equal SimplyPaginate::FIRST_PAGE_INDEX
|
32
17
|
end
|
33
18
|
|
34
|
-
|
35
|
-
|
36
|
-
SimplyPaginate::Paginator.per_page = 2
|
37
|
-
end
|
38
|
-
|
39
|
-
it "must be able to go back and foward" do
|
40
|
-
@paginator[1].next.elements.must_equal @paginator[2].elements
|
41
|
-
@paginator[1].previous.elements.must_equal @paginator[0].elements
|
42
|
-
end
|
19
|
+
it "must be able to retrieve it's elements" do
|
20
|
+
first_page.elements.must_equal [1, 2, 3]
|
43
21
|
end
|
44
22
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
23
|
+
it "must be able to compare with other page" do
|
24
|
+
first_page.must_equal first_page
|
25
|
+
first_page.wont_equal second_page
|
26
|
+
first_page.wont_equal Page.new(1, page_array_collection, 5)
|
27
|
+
first_page.must_equal Page.new(1, [1, 2, 3], 3)
|
50
28
|
end
|
51
29
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
@first_page.previous.must_be_nil
|
56
|
-
end
|
30
|
+
it "must be able to move forward" do
|
31
|
+
first_page.next.must_equal second_page
|
32
|
+
last_page.next.must_be_nil
|
57
33
|
end
|
58
34
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
@paginator[0].current?.must_equal false
|
63
|
-
@paginator[1].current?.must_equal true
|
64
|
-
end
|
65
|
-
|
66
|
-
it "must be setted as current when landed after previous" do
|
67
|
-
@paginator[1].previous
|
68
|
-
@paginator[1].current?.must_equal false
|
69
|
-
@paginator[0].current?.must_equal true
|
70
|
-
end
|
71
|
-
|
35
|
+
it "must be able to move backwards" do
|
36
|
+
first_page.previous.must_be_nil
|
37
|
+
second_page.previous.must_equal first_page
|
72
38
|
end
|
73
|
-
|
74
39
|
end
|
data/spec/paginator_spec.rb
CHANGED
@@ -1,50 +1,77 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
Paginator.per_page = 3
|
3
4
|
|
4
|
-
describe
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
describe Paginator do
|
6
|
+
include Helpers
|
7
|
+
|
8
|
+
let(:pages) { Paginator.new page_array_collection }
|
9
|
+
|
10
|
+
let(:first_page) { build_page 1 }
|
11
|
+
|
12
|
+
let(:last_page) { build_page 4 }
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
|
14
|
+
it "must be able to iterate using each" do
|
15
|
+
count = 0
|
16
|
+
results = []
|
17
|
+
|
18
|
+
pages.each do |page|
|
19
|
+
page.wont_be_nil
|
20
|
+
results << page.elements
|
21
|
+
|
22
|
+
count += 1
|
13
23
|
end
|
24
|
+
|
25
|
+
count.must_equal 4
|
26
|
+
results.must_equal [[1,2,3], [4,5,6], [7,8,9], [10]]
|
14
27
|
end
|
15
28
|
|
16
|
-
|
17
|
-
|
18
|
-
|
29
|
+
it "must be able to tell how many pages there are" do
|
30
|
+
pages.total_pages.must_equal 4
|
31
|
+
end
|
19
32
|
|
20
|
-
|
21
|
-
|
33
|
+
it "must be able to retrieve a certain page" do
|
34
|
+
pages[0].must_be_nil
|
35
|
+
pages[1].wont_be_nil
|
36
|
+
pages[1].must_equal first_page
|
37
|
+
pages[4].must_equal last_page
|
38
|
+
pages[5].must_be_nil
|
39
|
+
end
|
22
40
|
|
23
|
-
|
24
|
-
|
41
|
+
it "must be able to retrieve the first page" do
|
42
|
+
pages.first.must_equal first_page
|
43
|
+
end
|
25
44
|
|
26
|
-
|
27
|
-
|
28
|
-
|
45
|
+
it "must be able to retrieve the last page" do
|
46
|
+
pages.last.must_equal pages[4]
|
47
|
+
end
|
29
48
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
@paginator[0].next.wont_be_nil
|
49
|
+
describe "when iterating using 'start', 'next!' and 'next?'" do
|
50
|
+
it "must need to start before moving to the next " do
|
51
|
+
lambda { pages.next! }.must_raise NoMethodError
|
34
52
|
end
|
35
53
|
|
36
|
-
it
|
37
|
-
|
54
|
+
it "must move to the next page using 'next!'" do
|
55
|
+
iteration_pages = pages
|
56
|
+
iteration_pages.start
|
57
|
+
iteration_pages.next!
|
58
|
+
iteration_pages.current.must_equal build_page(2)
|
59
|
+
end
|
38
60
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
61
|
+
it "must retrieve the current page using 'current'" do
|
62
|
+
iteration_pages = pages
|
63
|
+
iteration_pages.current.must_be_nil
|
64
|
+
iteration_pages.start
|
65
|
+
iteration_pages.current.must_equal first_page
|
66
|
+
end
|
43
67
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
68
|
+
it "must retrieve if we can get a next value using 'next?'" do
|
69
|
+
iteration_pages = pages
|
70
|
+
iteration_pages.next?.must_equal false
|
71
|
+
iteration_pages.start
|
72
|
+
iteration_pages.next?.must_equal true
|
73
|
+
4.times { iteration_pages.next! }
|
74
|
+
iteration_pages.next?.must_equal false
|
48
75
|
end
|
49
76
|
end
|
50
77
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simply_paginate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-05-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -72,6 +72,8 @@ files:
|
|
72
72
|
- LICENSE.txt
|
73
73
|
- README.md
|
74
74
|
- Rakefile
|
75
|
+
- examples/data_mapper_example/Gemfile
|
76
|
+
- examples/data_mapper_example/test.rb
|
75
77
|
- lib/simply_paginate.rb
|
76
78
|
- lib/simply_paginate/not_in_range_error.rb
|
77
79
|
- lib/simply_paginate/page.rb
|