simply_paginate 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
- collection = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
30
+ include SimplyPaginate
29
31
 
30
- paginator = SimplyPaginate::Paginator.new(collection)
32
+ collection = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
31
33
 
32
- # create pages with max of 3 elements
33
- SimplyPaginate::Paginator.per_page 3
34
+ pages = Paginator.new(collection, 3)
34
35
 
35
36
  # retrieve a certain page
36
- paginator[0]
37
+ pages[1]
37
38
 
38
39
  #move through the pages freely
39
- paginator[0].next
40
- paginator[0].previous
40
+ pages[1].next
41
+ pages[1].previous
41
42
 
42
43
  #you might want the first element on the 3rd page
43
- paginator[0].next.next.next.previous.elements[0]
44
+ pages[1].next.next.next.previous.elements[0]
44
45
 
45
46
  #or maybe all of them
46
- paginator[0].next.next.next.previous.elements
47
- ```
47
+ pages[0].next.next.next.previous.elements
48
48
 
49
- There is also the possibility to use a DataMapper::Collection as the collection to be paginated (right out of the box, not extensions needed):
50
-
51
- ```ruby
52
- # I will guess you have a model called Post
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
- paginator = SimplyPaginate::Paginator.new(Post.all)
54
+ #or in a more old fashion way
55
+ pages.start
56
56
 
57
- paginator[0].elements # this will return a DataMapper::Collection with the first 10 elements
57
+ while pages.next? do
58
+ puts pages.current.elements
59
+
60
+ pages.next!
61
+ end
58
62
  ```
59
63
 
60
- ## Currently working on:
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
- * Adding support for common ORMs like: ActiveRecord, Sequel and DataMapper.
63
- * Testing...
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
- ## Alternative branch
66
- This branch contains a different implementation on the paging algorithm. This one creates pages on the fly and calculating offsets,
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
- Another modification is that the ```per_page``` value has moved up to the class, and there is no need on calling ```paginate``` anymore,
70
- also the ```pages``` has been dropped.
74
+ include SimplyPaginate
71
75
 
72
- ## Release 0.0.2 features:
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,7 @@
1
+ # A sample Gemfile
2
+ source "https://rubygems.org"
3
+
4
+ gem 'simply_paginate', github: 'guiman/simply_paginate'
5
+ gem 'data_mapper'
6
+ gem 'dm-sqlite-adapter'
7
+
@@ -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)
@@ -1,33 +1,35 @@
1
1
  module SimplyPaginate
2
2
  class Page
3
- attr_reader :first, :last
3
+ attr_reader :index, :collection, :size
4
4
 
5
- def initialize(first, last, paginator, previous_page = nil, next_page = nil)
6
- @first = first
7
- @last = last
8
- @paginator = paginator
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
- first = @last + 1
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
- first = @first - Paginator.per_page
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 current?
26
- !@paginator.current.nil? && @paginator.current.first == @first && @paginator.current.last == @last
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 elements
30
- @paginator.collection[@first..@last]
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
- @current = nil
19
+ @per_page = per_page
19
20
  end
20
21
 
21
- def [](pos)
22
- first = pos * @@per_page
23
- last = first + @@per_page - 1
22
+ ## Basic Operations
24
23
 
25
- ((first < 0) || (first >= self.collection.count)) ? nil : Page.new(first, last, self)
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 / @@per_page.to_f).ceil
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
@@ -1,3 +1,3 @@
1
1
  module SimplyPaginate
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
data/spec/page_spec.rb CHANGED
@@ -1,74 +1,39 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe SimplyPaginate::Page do
4
- before do
5
- SimplyPaginate::Paginator.per_page = 5
3
+ include SimplyPaginate
6
4
 
7
- @paginator = SimplyPaginate::Paginator.new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
8
- @first_page = SimplyPaginate::Page.new(0, 4, @paginator)
9
- @last_page = SimplyPaginate::Page.new(5, 9, @paginator)
5
+ describe Page do
6
+ include Helpers
10
7
 
11
- class SimplyPaginate::Page
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
- @first_page.next.paginator.wont_be_nil
23
- @first_page.next.previous.paginator.wont_be_nil
24
- end
10
+ let(:second_page) { build_page 2 }
25
11
 
26
- it "must be able to get the elements" do
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
- @first_page.next.elements.must_equal [6, 7, 8, 9, 10]
31
- @last_page.previous.elements.must_equal [1, 2, 3, 4, 5]
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
- describe "when having next and previous pages" do
35
- before do
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
- describe "when having previous and no next" do
46
- it "must be able to go back " do
47
- @last_page.next.must_be_nil
48
- @last_page.previous.elements.must_equal @first_page.elements
49
- end
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
- describe "when having next and no previous" do
53
- it "must be able to go back " do
54
- @first_page.next.elements.must_equal @last_page.elements
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
- describe "when moving to previous or next" do
60
- it "must be setted as current when landed after next" do
61
- @paginator[0].next
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
@@ -1,50 +1,77 @@
1
1
  require 'spec_helper'
2
2
 
3
+ Paginator.per_page = 3
3
4
 
4
- describe SimplyPaginate::Paginator do
5
- before do
6
- SimplyPaginate::Paginator.per_page = 3
7
- @paginator = SimplyPaginate::Paginator.new [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
8
- end
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
- describe 'before paginating' do
11
- it 'must be able to paginate' do
12
- @paginator.total_pages.must_equal 4
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
- describe 'after paginating' do
17
- before do
18
- SimplyPaginate::Paginator.per_page = 5
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
- @first_page = SimplyPaginate::Page.new(0, 4, @paginator)
21
- @last_page = SimplyPaginate::Page.new(5, 9, @paginator)
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
- @pages = [@first_page, @last_page]
24
- end
41
+ it "must be able to retrieve the first page" do
42
+ pages.first.must_equal first_page
43
+ end
25
44
 
26
- it 'must be able to paginate' do
27
- @paginator.total_pages.must_equal 2
28
- end
45
+ it "must be able to retrieve the last page" do
46
+ pages.last.must_equal pages[4]
47
+ end
29
48
 
30
- it 'must be able to retrieve a certain page' do
31
- @paginator[0].elements.must_equal @first_page.elements
32
- @paginator[0].previous.must_be_nil
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 'must be able to retrieve all pages' do
37
- @paginator.total_pages.must_equal 2
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
- #test first element
40
- @paginator[0].elements.must_equal @first_page.elements
41
- @paginator[0].previous.must_be_nil
42
- @paginator[0].next.wont_be_nil
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
- #test second element
45
- @paginator[1].elements.must_equal @last_page.elements
46
- @paginator[1].previous.wont_be_nil
47
- @paginator[1].next.must_be_nil
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
@@ -1,3 +1,13 @@
1
1
  require 'bundler'
2
2
  require 'minitest/autorun'
3
3
  Bundler.require
4
+
5
+ module Helpers
6
+ def page_array_collection
7
+ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
8
+ end
9
+
10
+ def build_page(number)
11
+ lambda { Page.new number, page_array_collection, 3 }.call
12
+ end
13
+ end
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.3
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-04-25 00:00:00.000000000 Z
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