paginator 1.0.0

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.
@@ -0,0 +1,3 @@
1
+ == 1.0.0 / 2006-10-23
2
+
3
+ * Initial release
@@ -0,0 +1,7 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/paginator
6
+ lib/paginator.rb
7
+ test/test_paginator.rb
@@ -0,0 +1,80 @@
1
+ paginator
2
+ by Bruce Williams
3
+ http://codefluency.com
4
+
5
+ == DESCRIPTION:
6
+
7
+ Paginator is a simple pagination class that provides a generic interface suitable
8
+ for use in any Ruby program.
9
+
10
+ == FEATURES/PROBLEMS:
11
+
12
+ Paginator doesn't make any assumptions as to how data is retrieved; you just
13
+ have to provide it with the total number of objects and a way to pull a specific
14
+ set of objects based on the offset and number of objects per page.
15
+
16
+ == SYNOPSIS:
17
+
18
+ === In a Rails Application
19
+
20
+ # In your controller
21
+ PER_PAGE = 20
22
+ @pager = Paginator.new(Foo.count, PER_PAGE) do |offset, per_page|
23
+ Foo.find(:all, :limit => per_page, :offset => offset)
24
+ end
25
+ @page = @pager.page(params[:page])
26
+
27
+ # In your view
28
+ <% @page.items.each do |foo| %>
29
+ <%# Show something for each item %>
30
+ <% end %>
31
+ <%= @page.number %>
32
+ <%= link_to("Prev", foos_url(:page => @page.prev.number)) if @page.prev? %>
33
+ <%= link_to("Next", foos_url(:page => @page.next.number)) if @page.next? %>
34
+
35
+ === Anything else
36
+
37
+ bunch_o_data = (1..60).to_a
38
+ PER_PAGE = 10
39
+ pager = Paginator.new(bunch_o_data.size, PER_PAGE) do |offset, per_page|
40
+ bunch_o_data[offset,per_page]
41
+ end
42
+ pager.each do |page|
43
+ puts "Page ##{page.number}"
44
+ page.each do |item|
45
+ puts item
46
+ end
47
+ end
48
+
49
+ == REQUIREMENTS:
50
+
51
+ None.
52
+
53
+ == INSTALL:
54
+
55
+ No special instructions.
56
+
57
+ == LICENSE:
58
+
59
+ (The MIT License)
60
+
61
+ Copyright (c) 2006 Bruce Williams (http://codefluency.com)
62
+
63
+ Permission is hereby granted, free of charge, to any person obtaining
64
+ a copy of this software and associated documentation files (the
65
+ 'Software'), to deal in the Software without restriction, including
66
+ without limitation the rights to use, copy, modify, merge, publish,
67
+ distribute, sublicense, and/or sell copies of the Software, and to
68
+ permit persons to whom the Software is furnished to do so, subject to
69
+ the following conditions:
70
+
71
+ The above copyright notice and this permission notice shall be
72
+ included in all copies or substantial portions of the Software.
73
+
74
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
75
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
76
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
77
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
78
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
79
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
80
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,19 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/paginator.rb'
6
+
7
+ Hoe.new('paginator', Paginator::VERSION) do |p|
8
+ p.rubyforge_name = 'paginator'
9
+ p.summary = 'A generic paginator object for use in any Ruby program'
10
+ p.description =<<EOD
11
+ Paginator doesn't make any assumptions as to how data is retrieved; you just
12
+ have to provide it with the total number of objects and a way to pull a specific
13
+ set of objects based on the offset and number of objects per page.
14
+ EOD
15
+ p.url = "http://paginator.rubyforge.org"
16
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
17
+ end
18
+
19
+ # vim: syntax=Ruby
File without changes
@@ -0,0 +1,107 @@
1
+ require 'forwardable'
2
+
3
+ class Paginator
4
+
5
+ VERSION = '1.0.0'
6
+
7
+ class ArgumentError < ::ArgumentError; end
8
+ class MissingCountError < ArgumentError; end
9
+ class MissingSelectError < ArgumentError; end
10
+
11
+ attr_reader :per_page
12
+
13
+ # Instantiate a new Paginator object
14
+ #
15
+ # Provide:
16
+ # * A total count of the number of objects to paginate
17
+ # * The number of objects in each page
18
+ # * A block that returns the array of items
19
+ # * The block is passed the item offset
20
+ # (and the number of items to show per page, for
21
+ # convenience)
22
+ def initialize(count, per_page, &select)
23
+ @count, @per_page = count, per_page
24
+ unless select
25
+ raise MissingSelectError, "Must provide block to select data for each page"
26
+ end
27
+ @select = select
28
+ end
29
+
30
+ # Total number of pages
31
+ def number_of_pages
32
+ (@count / @per_page) + (@count % @per_page > 0 ? 1 : 0)
33
+ end
34
+
35
+ # First page object
36
+ def first
37
+ page 1
38
+ end
39
+
40
+ # Last page object
41
+ def last
42
+ page number_of_pages
43
+ end
44
+
45
+ # Iterate through pages
46
+ def each
47
+ 1.upto(number_of_pages) do |number|
48
+ yield page(number)
49
+ end
50
+ end
51
+
52
+ # Retrieve page object by number
53
+ def page(number)
54
+ Page.new(self, number, lambda{ @select.call((number - 1) * @per_page, @per_page) })
55
+ end
56
+
57
+ # Page object
58
+ #
59
+ # Retrieves items for a page and provides metadata about the position
60
+ # of the page in the paginator
61
+ class Page
62
+
63
+ extend Forwardable
64
+ def_delegator :@pager, :first, :first
65
+ def_delegator :@pager, :last, :last
66
+ def_delegator :items, :each
67
+
68
+ attr_reader :number, :pager
69
+
70
+ def initialize(pager, number, select) #:nodoc:
71
+ @pager, @number = pager, number
72
+ @select = select
73
+ end
74
+
75
+ # Retrieve the items for this page
76
+ # * Caches
77
+ def items
78
+ @items ||= @select.call
79
+ end
80
+
81
+ # Checks to see if there's a page before this one
82
+ def prev?
83
+ @number > 1
84
+ end
85
+
86
+ # Get previous page (if possible)
87
+ def prev
88
+ @pager.page(@number - 1) if prev?
89
+ end
90
+
91
+ # Checks to see if there's a page after this one
92
+ def next?
93
+ @number < @pager.number_of_pages
94
+ end
95
+
96
+ # Get next page (if possible)
97
+ def next
98
+ @pager.page(@number + 1) if next?
99
+ end
100
+
101
+ def ==(other) #:nodoc:
102
+ @pager == other.pager && self.number == other.number
103
+ end
104
+
105
+ end
106
+
107
+ end
@@ -0,0 +1,76 @@
1
+ require 'test/unit'
2
+ require 'paginator'
3
+
4
+ class PaginatorTest < Test::Unit::TestCase
5
+
6
+ PER_PAGE = 10
7
+
8
+ def setup
9
+ @data = (0..43).to_a
10
+ @pager = Paginator.new(@data.size, PER_PAGE) do |offset,per_page|
11
+ @data[offset,per_page]
12
+ end
13
+ end
14
+
15
+ def test_initializing_paginator_raises_exception
16
+ assert_raises(Paginator::MissingSelectError) do
17
+ @pager = Paginator.new(@data.size, PER_PAGE)
18
+ end
19
+ end
20
+
21
+ def test_can_get_last_page_from_page_object
22
+ assert_equal @pager.last, @pager.page(2).last
23
+ end
24
+
25
+ def test_can_get_first_page_from_page_object
26
+ assert_equal @pager.first, @pager.page(2).first
27
+ end
28
+
29
+ def test_does_not_exceed_per_page
30
+ @pager.each do |page|
31
+ assert page.items.size <= PER_PAGE
32
+ end
33
+ end
34
+
35
+ def test_only_last_page_has_less_items
36
+ @pager.each do |page|
37
+ if page != @pager.last
38
+ assert page.items.size <= PER_PAGE
39
+ else
40
+ assert page.items.size < PER_PAGE
41
+ end
42
+ end
43
+ end
44
+
45
+ def test_returns_correct_first_page
46
+ assert_equal @pager.page(1).number, @pager.first.number
47
+ end
48
+
49
+ def test_returns_correct_last_page
50
+ assert_equal @pager.page(5).number, @pager.last.number
51
+ end
52
+
53
+ def test_last_page_has_no_next_page
54
+ assert !@pager.last.next?
55
+ assert !@pager.last.next
56
+ end
57
+
58
+ def test_first_page_has_no_prev_page
59
+ assert !@pager.first.prev?
60
+ assert !@pager.first.prev
61
+ end
62
+
63
+ def test_each
64
+ @pager.each do |page|
65
+ assert page
66
+ page.each do |item|
67
+ assert item
68
+ end
69
+ end
70
+ end
71
+
72
+ def test_number_of_pages
73
+ assert_equal 5, @pager.number_of_pages
74
+ end
75
+
76
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: paginator
5
+ version: !ruby/object:Gem::Version
6
+ version: 1.0.0
7
+ date: 2006-10-23 00:00:00 -06:00
8
+ summary: A generic paginator object for use in any Ruby program
9
+ require_paths:
10
+ - lib
11
+ - test
12
+ email: ryand-ruby@zenspider.com
13
+ homepage: http://paginator.rubyforge.org
14
+ rubyforge_project: paginator
15
+ description: Paginator doesn't make any assumptions as to how data is retrieved; you just have to provide it with the total number of objects and a way to pull a specific set of objects based on the offset and number of objects per page.
16
+ autorequire:
17
+ default_executable:
18
+ bindir: bin
19
+ has_rdoc: true
20
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
21
+ requirements:
22
+ - - ">"
23
+ - !ruby/object:Gem::Version
24
+ version: 0.0.0
25
+ version:
26
+ platform: ruby
27
+ signing_key:
28
+ cert_chain:
29
+ authors:
30
+ - Ryan Davis
31
+ files:
32
+ - History.txt
33
+ - Manifest.txt
34
+ - README.txt
35
+ - Rakefile
36
+ - bin/paginator
37
+ - lib/paginator.rb
38
+ - test/test_paginator.rb
39
+ test_files: []
40
+
41
+ rdoc_options: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ executables:
46
+ - paginator
47
+ extensions: []
48
+
49
+ requirements: []
50
+
51
+ dependencies:
52
+ - !ruby/object:Gem::Dependency
53
+ name: hoe
54
+ version_requirement:
55
+ version_requirements: !ruby/object:Gem::Version::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 1.1.2
60
+ version: