taylorbarstow-simple_pagination 0.1.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.
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 0
3
+ :major: 0
4
+ :minor: 1
@@ -0,0 +1,3 @@
1
+ %w(page page_collection).each do |f|
2
+ require File.join(File.dirname(__FILE__), 'simple_pagination', f)
3
+ end
@@ -0,0 +1,59 @@
1
+ module SimplePagination
2
+ class Page
3
+ def initialize(number, collection)
4
+ @number, @collection = number, collection
5
+ end
6
+
7
+ ##
8
+ # The zero-based offset of the first record in this page
9
+ def offset
10
+ (@number-1) * @collection.page_size + 1
11
+ end
12
+
13
+ ##
14
+ # The one-based page number for this page
15
+ def number
16
+ @number
17
+ end
18
+
19
+ ##
20
+ # The Page object after this page (or +nil+ if +self.last?+)
21
+ def next
22
+ @collection[number + 1]
23
+ end
24
+
25
+ ##
26
+ # The Page object before this page (or +nil+ if +self.first?+)
27
+ def prev
28
+ @collection[number - 1]
29
+ end
30
+
31
+ ##
32
+ # Test if this is the first page in the collection
33
+ def first?
34
+ number == 1
35
+ end
36
+
37
+ ##
38
+ # Test if this is the last page in the collection
39
+ def last?
40
+ number == @collection.length
41
+ end
42
+
43
+ ##
44
+ # Test if this is the current page.
45
+ def current?
46
+ self === @collection.current
47
+ end
48
+
49
+ ##
50
+ # Generate a "window" of pages around (and including) this page. +n+
51
+ # is the number of pages to show (defaults to 10). For example, if this is
52
+ # page 8 and you ask for window(10) you will get an array of Page objects
53
+ # representing the following pages: 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
54
+ def window(n=10)
55
+ start = [1, [number-(n/2)+1, @collection.length-n+1].min].max
56
+ (start..start+n-1).collect {|i| @collection[i]}.compact
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,68 @@
1
+ module SimplePagination
2
+ class PageCollection
3
+ ##
4
+ # Create a new PageCollection object. The following options are available.
5
+ # [:current_offset] The zero-based offset of the first record in the current page of results
6
+ # [:current_page] The one-based offset of the current page of results
7
+ # [:total] The total number of results across all pages
8
+ # [:page_size] The page size
9
+ #
10
+ # You can choose between :current_offset and :current_page based on your
11
+ # needs. Same goes for :total_records and :total_pages. :page_size
12
+ # is required.
13
+ #
14
+ # A typical use of this class would be to define a <tt>pages</tt> method on your
15
+ # result set class which returns an instance of PageCollection. (So you can
16
+ # do, e.g., <tt>my_result_set.pages.current</tt> and so on.)
17
+ def initialize(options={})
18
+ check_options(options)
19
+ @pages, @page_size = {}, options[:page_size]
20
+ @length = options[:total_pages] || options[:total_records] / @page_size
21
+ @current_page = options[:current_page] || (options[:current_offset]/@page_size)+1
22
+ end
23
+
24
+ ##
25
+ # A Page object representing the page at a given page number (one-based).
26
+ def [](i)
27
+ @pages[i] ||= Page.new(i, self) unless out_of_bounds?(i)
28
+ end
29
+
30
+ ##
31
+ # A Page object representing the current page in the collection.
32
+ def current
33
+ self[@current_page]
34
+ end
35
+
36
+ ##
37
+ # A Page object representing the first page in the collection.
38
+ def first
39
+ self[1]
40
+ end
41
+
42
+ ##
43
+ # A Page object representing the last page in the collection.
44
+ def last
45
+ self[length]
46
+ end
47
+
48
+ ##
49
+ # The number of pages in the collection.
50
+ attr_reader :length
51
+
52
+ ##
53
+ # The number of records shown on each page in the collection.
54
+ attr_reader :page_size
55
+
56
+ private
57
+
58
+ def check_options(options)
59
+ raise ArgumentError, "requires :current_offset or :current_page" unless options[:current_offset] || options[:current_page]
60
+ raise ArgumentError, "requires :page_size" unless options[:page_size]
61
+ raise ArgumentError, "requires :total" unless options[:total_pages] or options[:total_records]
62
+ end
63
+
64
+ def out_of_bounds?(i)
65
+ i > length || i < 1
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,99 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper.rb')
2
+
3
+ class PageCollectionTest < Test::Unit::TestCase
4
+ include SimplePagination
5
+
6
+ context "creating a new instance" do
7
+ should "require :current_offset or :current_page" do
8
+ args = {:page_size => 10, :total_records => 100}
9
+ assert_raise(ArgumentError) {PageCollection.new(args)}
10
+ assert_nothing_raised {PageCollection.new(args.merge(:current_offset => 0))}
11
+ assert_nothing_raised {PageCollection.new(args.merge(:current_page => 1))}
12
+ end
13
+
14
+ should "require :total_records or :total_pages" do
15
+ args = {:page_size => 10, :current_page => 1}
16
+ assert_raise(ArgumentError) {PageCollection.new(args)}
17
+ assert_nothing_raised {PageCollection.new(args.merge(:total_pages => 10))}
18
+ assert_nothing_raised {PageCollection.new(args.merge(:total_records => 10))}
19
+ end
20
+
21
+ should "require :page_size" do
22
+ args = {:total_records => 100, :current_offset => 0}
23
+ assert_raise(ArgumentError) {PageCollection.new(args)}
24
+ assert_nothing_raised {PageCollection.new(args.merge(:page_size => 10))}
25
+ end
26
+ end
27
+
28
+ context "accessors" do
29
+ setup do
30
+ @collection = PageCollection.new(:total_pages => 10, :page_size => 10, :current_offset => 0)
31
+ end
32
+
33
+ should "provide page_size accessor" do
34
+ assert_equal 10, @collection.page_size
35
+ end
36
+
37
+ should "provide length accessor" do
38
+ assert_equal 10, @collection.length
39
+ end
40
+
41
+ should "calculate length when given :total_records" do
42
+ c = PageCollection.new(:total_records => 113, :page_size => 3, :current_offset => 0)
43
+ assert_equal 37, c.length
44
+ end
45
+ end
46
+
47
+ context "accessing a specific page" do
48
+ setup do
49
+ @collection = PageCollection.new(:total_pages => 10, :page_size => 10, :current_page=>1)
50
+ end
51
+
52
+ should "create and return a new Page instance" do
53
+ p = Page.new(1, @collection)
54
+ Page.expects(:new).with(1, @collection).returns(p)
55
+ assert_same p, @collection[1]
56
+ end
57
+
58
+ should "return the same Page across multiple invocations" do
59
+ assert_same @collection[3], @collection[3]
60
+ assert_not_same @collection[3], @collection[4]
61
+ end
62
+
63
+ context "when the page is out of bounds" do
64
+ should "return nil" do
65
+ assert_equal nil, @collection[100]
66
+ assert_equal nil, @collection[0]
67
+ assert_equal nil, @collection[-1]
68
+ end
69
+ end
70
+ end
71
+
72
+ context "accessing named pages" do
73
+ setup do
74
+ @collection = PageCollection.new(:total_pages => 10, :page_size => 10, :current_page=>1)
75
+ end
76
+
77
+ should "access current page" do
78
+ (1..3).each do |i|
79
+ c = PageCollection.new(:total_pages => 10, :page_size => 10, :current_page=>i)
80
+ c.expects(:[]).with(i)
81
+ c.current
82
+ end
83
+ end
84
+
85
+ should "access first page" do
86
+ @collection.expects(:[]).with(1)
87
+ @collection.first
88
+ end
89
+
90
+ should "access last page" do
91
+ @collection.expects(:[]).with(10)
92
+ @collection.last
93
+
94
+ c = PageCollection.new(:total_records => 113, :page_size => 3, :current_page => 1)
95
+ c.expects(:[]).with(37)
96
+ c.last
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,108 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper.rb')
2
+
3
+ class PageTest < Test::Unit::TestCase
4
+ include SimplePagination
5
+
6
+ def assert_page_window(expected, actual)
7
+ actual.each {|page| assert_instance_of Page, page}
8
+ assert_equal expected, actual.collect {|page| page.number}
9
+ end
10
+
11
+ context "accessors" do
12
+ setup do
13
+ @collection = PageCollection.new(:current_page => 1, :total_pages => 10, :page_size => 10)
14
+ @page = Page.new(5, @collection)
15
+ end
16
+
17
+ should "provide accessor for page number" do
18
+ assert_equal 5, @page.number
19
+ end
20
+
21
+ should "provide accessor for first record offset" do
22
+ assert_equal 41, @page.offset
23
+ end
24
+ end
25
+
26
+ context "next/previous page" do
27
+ setup do
28
+ @collection = PageCollection.new(:current_page => 1, :total_pages => 10, :page_size => 10)
29
+ end
30
+
31
+ should "provide previous page using PageCollection#[]" do
32
+ @collection.expects(:[]).with(2)
33
+ Page.new(3, @collection).prev
34
+
35
+ @collection.expects(:[]).with(4)
36
+ Page.new(5, @collection).prev
37
+ end
38
+
39
+ should "provide next page using PageCollection#[]" do
40
+ @collection.expects(:[]).with(2)
41
+ Page.new(1, @collection).next
42
+
43
+ @collection.expects(:[]).with(4)
44
+ Page.new(3, @collection).next
45
+ end
46
+ end
47
+
48
+ context "named page tests" do
49
+ setup do
50
+ @collection = PageCollection.new(:current_page => 1, :total_pages => 10, :page_size => 10)
51
+ end
52
+
53
+ should "identify last page" do
54
+ assert @collection[10].last?
55
+ end
56
+
57
+ should "not identify non last page as last" do
58
+ (1..9).each {|i| assert !@collection[i].last?}
59
+ end
60
+
61
+ should "identify first page" do
62
+ assert @collection[1].first?
63
+ end
64
+
65
+ should "not identify non first page as first" do
66
+ (2..10).each {|i| assert !@collection[i].first?}
67
+ end
68
+
69
+ should "identify current page" do
70
+ assert @collection[1].current?
71
+ end
72
+
73
+ should "not identify non current page as current" do
74
+ (2..10).each {|i| assert !@collection[i].current?}
75
+ end
76
+ end
77
+
78
+ context "generating a page window" do
79
+ setup do
80
+ @collection = PageCollection.new(:current_page => 1, :page_size => 10, :total_pages => 50)
81
+ end
82
+
83
+ should "generate page window of the requested size" do
84
+ assert_equal 10, @collection[10].window(10).length
85
+ assert_equal 5, @collection[10].window(5).length
86
+ end
87
+
88
+ should "generate page window when near beginning" do
89
+ (1..5).each do |i|
90
+ assert_page_window (1..10).to_a, @collection[i].window(10)
91
+ end
92
+ end
93
+
94
+ should "generate page window when in middle" do
95
+ assert_page_window (20..29).to_a, @collection[24].window(10)
96
+ end
97
+
98
+ should "generate page window when near end" do
99
+ (46..50).each do |i|
100
+ assert_page_window (41..50).to_a, @collection[i].window(10)
101
+ end
102
+ end
103
+
104
+ should "generate page window when requesting window larger than # of pages" do
105
+ assert_page_window (1..50).to_a, @collection[1].window(100)
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,5 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'simple_pagination')
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: taylorbarstow-simple_pagination
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Taylor Barstow
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-11 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: A simple, standalone pagination gem for non-ActiveRecord data.
17
+ email: taylorbarstow@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - VERSION.yml
26
+ - lib/simple_pagination
27
+ - lib/simple_pagination/page.rb
28
+ - lib/simple_pagination/page_collection.rb
29
+ - lib/simple_pagination.rb
30
+ - test/simple_pagination
31
+ - test/simple_pagination/page_collection_test.rb
32
+ - test/simple_pagination/page_test.rb
33
+ - test/test_helper.rb
34
+ has_rdoc: true
35
+ homepage: http://github.com/taylorbarstow/simple_pagination
36
+ post_install_message:
37
+ rdoc_options:
38
+ - --inline-source
39
+ - --charset=UTF-8
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ requirements: []
55
+
56
+ rubyforge_project:
57
+ rubygems_version: 1.2.0
58
+ signing_key:
59
+ specification_version: 2
60
+ summary: A simple, standalone pagination gem non-ActiveRecord data.
61
+ test_files: []
62
+