dm-pager 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/History.md ADDED
@@ -0,0 +1,42 @@
1
+
2
+ 0.0.7 / 2009-10-10
3
+ ==================
4
+
5
+ * Renamed to dm-pager (available on gemcutter)
6
+
7
+ 0.0.6 / 2009-10-08
8
+ ==================
9
+
10
+ * Added #option and specs for overriding defaults with #to_html [#13]
11
+ * Added "jump" class to first,last,prev,next <li>'s [#17]
12
+ * Added ability to configure "..." text when more pages are available
13
+
14
+ 0.0.5 / 2009-10-07
15
+ ==================
16
+
17
+ * #to_f -> #quo
18
+ * Fixed pager from being rendered when only one page is available
19
+
20
+ 0.0.4 / 2009-10-07
21
+ ==================
22
+
23
+ * Added DataMapper::Pagination#pager_option
24
+ * Fixed :per_page; now may be 'per_page' as well
25
+ * Fixed :per_page; now allows for numeric strings
26
+
27
+ 0.0.3 / 2009-10-07
28
+ ==================
29
+
30
+ * Fixed issue caused by indifferent params hash having both :page and 'page' keys
31
+
32
+ 0.0.2 / 2009-10-07
33
+ ==================
34
+
35
+ * Allowing #page :page param, as alternative to the current_page arg (User.page(params) vs User.page(params[:page]))
36
+ * Fixed issue when page is a string (from query string); Coerce strings to ints
37
+ * Fixed issue when page is nil; now considered first page
38
+
39
+ 0.0.1 / 2009-10-07
40
+ ===================
41
+
42
+ * Initial release
data/Manifest ADDED
@@ -0,0 +1,20 @@
1
+ History.md
2
+ Manifest
3
+ Rakefile
4
+ Readme.md
5
+ examples/pager.rb
6
+ lib/dm-pager.rb
7
+ lib/dm-pager/defaults.rb
8
+ lib/dm-pager/helpers.rb
9
+ lib/dm-pager/helpers/rails.rb
10
+ lib/dm-pager/pager.rb
11
+ lib/dm-pager/pagination.rb
12
+ lib/dm-pager/version.rb
13
+ spec/integration/rails_helper_spec.rb
14
+ spec/spec.opts
15
+ spec/spec_helper.rb
16
+ spec/unit/pager_spec.rb
17
+ spec/unit/pagination_spec.rb
18
+ tasks/docs.rake
19
+ tasks/gemspec.rake
20
+ tasks/spec.rake
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+
2
+ $:.unshift 'lib'
3
+ require 'rubygems'
4
+ require 'dm-pager'
5
+ require 'rake'
6
+ require 'echoe'
7
+
8
+ Echoe.new "dm-pager", DataMapper::Pagination::VERSION do |p|
9
+ p.author = "TJ Holowaychuk"
10
+ p.email = "tj@vision-media.ca"
11
+ p.summary = "DataMapper Pagination"
12
+ p.url = "http://github.com/visionmedia/dm-pagination"
13
+ p.runtime_dependencies = []
14
+ p.runtime_dependencies << 'dm-core >=0.10.1'
15
+ p.runtime_dependencies << 'dm-aggregates >=0.10.1'
16
+ end
17
+
18
+ Dir['tasks/**/*.rake'].sort.each { |f| load f }
data/Readme.md ADDED
@@ -0,0 +1,119 @@
1
+
2
+ # DataMapper::Pager
3
+
4
+ Better paging solution for DataMapper for DM >= 0.10.1
5
+
6
+ # About
7
+
8
+ Not to be confused with the dm-pagination gem (a similar gem lacking in functionality) dm-pager
9
+ is a new, fresh, and feature rich pagination implementation for DataMapper. Due to Github's gem builder
10
+ being destroyed, we were forced to rename our gem to 'dm-pager' which is now available on [Gemcutter.org](http://gemcutter.org).
11
+
12
+ # Installation
13
+
14
+ Install [Gemcutter](http://gemcutter.org) and execute:
15
+ $ sudo gem install dm-pager
16
+
17
+ # Examples
18
+
19
+ Page 1 for all items, defaulting to 6 per page:
20
+ Item.page
21
+ // => [1, 2, 3, 4, 5, 6]
22
+
23
+ Page 2 for all items, 6 per page, with only 3 items remaining
24
+ Item.page 2
25
+ // => [7, 8, 9]
26
+
27
+ Page 3, 2 per page:
28
+ Item.page 3, :per_page => 2
29
+ // => [5, 6]
30
+
31
+ Accessing the pager instance:
32
+ Item.page(1, :per_page => 4).pager
33
+ // => #<DataMapper::Pager:0x1610f20 @per_page=4, @next_page=2, @total_pages=3, @total=10, @current_page=1>
34
+
35
+ Converting to HTML:
36
+ Item.page(2).pager.to_html('/items')
37
+ // => "<div class=\"pager\">..."
38
+
39
+ Alter the number of intermediate numbered links displayed, defaults to 7
40
+ Item.page(2).pager.to_html('/items', :size => 3)
41
+ // => "<div class=\"pager\">..."
42
+
43
+ # Output
44
+
45
+ Output is displayed in a format similar to below, although
46
+ with CSS you may hide anything you wish to remove. There is
47
+ no need to provide an API for this.
48
+
49
+ Item.page(2).pager.to_html('/items', :size => 3)
50
+ // => First Previous 1 [2] 3 ... Next Last
51
+
52
+ Item.page.pager.to_html '/items'
53
+ // => [1] 2 3 4 5 6 7 ... Next Last
54
+
55
+ Item.page(5).pager.to_html('/items', :size => 5)
56
+ // => First Previous ... 3 4 [5] 6 7 ... Next Last
57
+
58
+ # Markup
59
+
60
+ Sample query:
61
+ Item.page(2, :per_page => 2).pager.to_html("/items", :size => 3)
62
+
63
+ Sample markup:
64
+
65
+ <div class="pager">
66
+ <a href="/items?page=1" class="first">First</a>
67
+ <a href="/items?page=1" class="previous">Previous</a>
68
+ <ul>
69
+ <li class="page-1 first"><a href="/items?page=1" class="">1</a></li>
70
+ <li class="active page-2"><a href="/items?page=2" class="">2</a></li>
71
+ <li class="page-3 last"><a href="/items?page=3" class="">3</a></li>
72
+ <li class="more">...</li>
73
+ </ul>
74
+ <a href="/items?page=3" class="next">Next</a>
75
+ <a href="/items?page=5" class="last">Last</a>
76
+ </div>
77
+
78
+ ## Running Specs
79
+
80
+ Autospec:
81
+ $ autospec
82
+
83
+ Rake:
84
+ $ rake spec
85
+ $ rake spec:verbose
86
+ $ rake spec:select SPEC=spec/unit/pager_spec.rb
87
+
88
+ RSpec:
89
+ $ spec --color spec
90
+
91
+ ## Authors
92
+
93
+ * TJ Holowaychuk <tj@vision-media.ca>
94
+ * Marco Otte-Witte <http://simplabs.com>
95
+
96
+ ## License
97
+
98
+ (The MIT License)
99
+
100
+ Copyright (c) 2009 TJ Holowaychuk <tj@vision-media.ca>
101
+
102
+ Permission is hereby granted, free of charge, to any person obtaining
103
+ a copy of this software and associated documentation files (the
104
+ 'Software'), to deal in the Software without restriction, including
105
+ without limitation the rights to use, copy, modify, merge, publish,
106
+ distribute, sublicense, an d/or sell copies of the Software, and to
107
+ permit persons to whom the Software is furnished to do so, subject to
108
+ the following conditions:
109
+
110
+ The above copyright notice and this permission notice shall be
111
+ included in all copies or substantial portions of the Software.
112
+
113
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
114
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
115
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
116
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
117
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
118
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
119
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/dm-pager.gemspec ADDED
@@ -0,0 +1,36 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{dm-pager}
5
+ s.version = "0.0.7"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["TJ Holowaychuk"]
9
+ s.date = %q{2009-10-10}
10
+ s.description = %q{DataMapper Pagination}
11
+ s.email = %q{tj@vision-media.ca}
12
+ s.extra_rdoc_files = ["lib/dm-pager.rb", "lib/dm-pager/defaults.rb", "lib/dm-pager/helpers.rb", "lib/dm-pager/helpers/rails.rb", "lib/dm-pager/pager.rb", "lib/dm-pager/pagination.rb", "lib/dm-pager/version.rb", "tasks/docs.rake", "tasks/gemspec.rake", "tasks/spec.rake"]
13
+ s.files = ["History.md", "Manifest", "Rakefile", "Readme.md", "examples/pager.rb", "lib/dm-pager.rb", "lib/dm-pager/defaults.rb", "lib/dm-pager/helpers.rb", "lib/dm-pager/helpers/rails.rb", "lib/dm-pager/pager.rb", "lib/dm-pager/pagination.rb", "lib/dm-pager/version.rb", "spec/integration/rails_helper_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/pager_spec.rb", "spec/unit/pagination_spec.rb", "tasks/docs.rake", "tasks/gemspec.rake", "tasks/spec.rake", "dm-pager.gemspec"]
14
+ s.homepage = %q{http://github.com/visionmedia/dm-pagination}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Dm-pager", "--main", "Readme.md"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{dm-pager}
18
+ s.rubygems_version = %q{1.3.5}
19
+ s.summary = %q{DataMapper Pagination}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
+ s.add_runtime_dependency(%q<dm-core>, [">= 0.10.1"])
27
+ s.add_runtime_dependency(%q<dm-aggregates>, [">= 0.10.1"])
28
+ else
29
+ s.add_dependency(%q<dm-core>, [">= 0.10.1"])
30
+ s.add_dependency(%q<dm-aggregates>, [">= 0.10.1"])
31
+ end
32
+ else
33
+ s.add_dependency(%q<dm-core>, [">= 0.10.1"])
34
+ s.add_dependency(%q<dm-aggregates>, [">= 0.10.1"])
35
+ end
36
+ end
data/examples/pager.rb ADDED
@@ -0,0 +1,38 @@
1
+
2
+ $:.unshift File.dirname(__FILE__) + '/../lib'
3
+
4
+ require 'rubygems'
5
+ require 'dm-core'
6
+ require 'dm-pager'
7
+
8
+ class Item
9
+ include DataMapper::Resource
10
+ property :id, Serial
11
+ end
12
+
13
+ DataMapper.setup :default, 'sqlite3::memory:'
14
+ DataMapper.auto_migrate!
15
+ (1..10).each { |n| Item.create }
16
+
17
+ def show example
18
+ puts example
19
+ expr = eval example
20
+ if String === expr
21
+ puts expr + "\n\n"
22
+ else
23
+ puts "# => #{eval(example).inspect}\n\n"
24
+ end
25
+ end
26
+
27
+ puts "Items: #{Item.all.count}\n\n"
28
+ show 'Item.page'
29
+ show 'Item.page(2)'
30
+ show 'Item.page(1, :per_page => 4)'
31
+ show 'Item.page(1, :per_page => 4).pager'
32
+ show 'Item.page(1, :per_page => 4).pager.to_html "/items" '
33
+ show 'Item.page(1, :per_page => 4).pager.to_html "/items?foo=bar" '
34
+ show 'Item.page(2, :per_page => 4).pager.to_html "/items?page=2" '
35
+ show 'Item.page(1, :per_page => 2).pager.to_html("/items", :size => 3)'
36
+ show 'Item.page(2, :per_page => 2).pager.to_html("/items", :size => 3)'
37
+ show 'Item.page(3, :per_page => 2).pager.to_html("/items", :size => 3)'
38
+ show 'Item.page(4, :per_page => 2).pager.to_html("/items", :size => 3)'
@@ -0,0 +1,40 @@
1
+
2
+ module DataMapper
3
+ module Pagination
4
+
5
+ @defaults = {
6
+ :per_page => 6,
7
+ :size => 7,
8
+ :pager_class => 'pager',
9
+ :previous_text => 'Previous',
10
+ :next_text => 'Next',
11
+ :first_text => 'First',
12
+ :last_text => 'Last',
13
+ :more_text => '...'
14
+ }
15
+
16
+ ##
17
+ # Default pagination values.
18
+ #
19
+ # === Options
20
+ #
21
+ # :per_page Records per page; defaults to 6
22
+ # :size Number of intermediate page number links to be shown; Defaults to 7
23
+ # :pager_class Class for the div that contains the pagination links, defaults to 'pager'
24
+ # :previous_text Text for the 'previous' link, defaults to 'Previous'
25
+ # :next_text Text for the 'next' link, defaults to 'Next'
26
+ # :first_text Text for the 'first' link, defaults to 'First'
27
+ # :last_text Text for the 'last' link, defaults to 'Last'
28
+ # :more_text Text for the 'more' indicator, defaults to '...'
29
+ #
30
+ # === Examples
31
+ #
32
+ # DataMapper::Pagination.defaults[:size] = 5
33
+ #
34
+
35
+ def self.defaults
36
+ @defaults
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,17 @@
1
+
2
+ module DataMapper::Pagination::Helpers::Rails
3
+
4
+ ##
5
+ # Renders the pagination links for the given _collection_.
6
+ #
7
+ # === Options
8
+ #
9
+ # :params Hash of params that is passed to url_for
10
+ # :size Number of intermediate page number links to be shown; Defaults to 7
11
+
12
+ def paginate collection, options = {}
13
+ uri = @template.url_for @template.params.merge(options[:params] || {})
14
+ collection.pager.to_html uri, options
15
+ end
16
+
17
+ end
@@ -0,0 +1,6 @@
1
+
2
+ module DataMapper::Pagination
3
+ module Helpers
4
+ autoload :Rails, 'dm-pager/helpers/rails'
5
+ end
6
+ end
@@ -0,0 +1,193 @@
1
+
2
+ module DataMapper
3
+ class Pager
4
+
5
+ ##
6
+ # Total number of un-limited records.
7
+
8
+ attr_reader :total
9
+
10
+ ##
11
+ # Records per page.
12
+
13
+ attr_reader :per_page
14
+
15
+ ##
16
+ # Current page number.
17
+
18
+ attr_reader :current_page
19
+
20
+ ##
21
+ # Previous page or nil when no previous page is available.
22
+
23
+ attr_reader :previous_page
24
+
25
+ ##
26
+ # Next page or nil when no more pages are available.
27
+
28
+ attr_reader :next_page
29
+
30
+ ##
31
+ # Total number of pages.
32
+
33
+ attr_reader :total_pages
34
+
35
+ ##
36
+ # Initialize with _options_.
37
+
38
+ def initialize options = {}
39
+ @total = options.delete :total
40
+ @per_page = options.delete :limit
41
+ @current_page = options.delete :page
42
+ @total_pages = total.quo(per_page).ceil
43
+ @next_page = current_page + 1 unless current_page >= total_pages
44
+ @previous_page = current_page - 1 unless current_page <= 1
45
+ end
46
+
47
+ ##
48
+ # Render the pager with the given _uri_ and _options_.
49
+ #
50
+ # === Examples
51
+ #
52
+ # User.page(2).pager.to_html('/users')
53
+ # User.page(2).pager.to_html('/users', :size => 3)
54
+ #
55
+ # === Options
56
+ #
57
+ # :size Number of intermediate page number links to be shown; Defaults to 7
58
+ #
59
+
60
+ def to_html uri, options = {}
61
+ return unless total_pages > 1
62
+ @uri, @options = uri, options
63
+ @size = option :size
64
+ raise ArgumentError, 'invalid :size; must be an odd number' if @size % 2 == 0
65
+ @size /= 2
66
+ [%(<ul class="#{Pagination.defaults[:pager_class]}">),
67
+ first_link,
68
+ previous_link,
69
+ more(:before),
70
+ intermediate_links.join("\n"),
71
+ more(:after),
72
+ next_link,
73
+ last_link,
74
+ '</ul>'].join
75
+ end
76
+
77
+ private
78
+
79
+ ##
80
+ # Fetch _key_ from the options passed to #to_html, or
81
+ # its default value.
82
+
83
+ def option key
84
+ @options.fetch key, Pagination.defaults[key]
85
+ end
86
+
87
+ ##
88
+ # Link to _page_ with optional anchor tag _contents_.
89
+
90
+ def link_to page, contents = nil
91
+ %(<a href="#{uri_for(page)}">#{contents || page}</a>)
92
+ end
93
+
94
+ ##
95
+ # More pages indicator for _position_.
96
+
97
+ def more position
98
+ return '' if position == :before && (current_page <= 1 || first <= 1)
99
+ return '' if position == :after && (current_page >= total_pages || last >= total_pages)
100
+ li 'more', option(:more_text)
101
+ end
102
+
103
+ ##
104
+ # Intermediate page links array.
105
+
106
+ def intermediate_links
107
+ (first..last).map do |page|
108
+ classes = ["page-#{page}"]
109
+ classes << 'active' if current_page == page
110
+ li classes.join(' '), link_to(page)
111
+ end
112
+ end
113
+
114
+ ##
115
+ # Previous link.
116
+
117
+ def previous_link
118
+ li 'previous jump', link_to(previous_page, option(:previous_text)) if previous_page
119
+ end
120
+
121
+ ##
122
+ # Next link.
123
+
124
+ def next_link
125
+ li 'next jump', link_to(next_page, option(:next_text)) if next_page
126
+ end
127
+
128
+ ##
129
+ # Last link.
130
+
131
+ def last_link
132
+ li 'last jump', link_to(total_pages, option(:last_text)) if next_page
133
+ end
134
+
135
+ ##
136
+ # First link.
137
+
138
+ def first_link
139
+ li 'first jump', link_to(1, option(:first_text)) if previous_page
140
+ end
141
+
142
+ ##
143
+ # Determine first intermediate page.
144
+
145
+ def first
146
+ @first ||= begin
147
+ first = [current_page - @size, 1].max
148
+ if (current_page - total_pages).abs < @size
149
+ first = [first - (@size - (current_page - total_pages).abs), 1].max
150
+ end
151
+ first
152
+ end
153
+ end
154
+
155
+ ##
156
+ # Determine last intermediate page.
157
+
158
+ def last
159
+ @last ||= begin
160
+ last = [current_page + @size, total_pages].min
161
+ if @size >= current_page
162
+ last = [last + (@size - current_page) + 1, total_pages].min
163
+ end
164
+ last
165
+ end
166
+ end
167
+
168
+ ##
169
+ # Renders a <li> with the given _css_class_ and _contents_.
170
+
171
+ def li css_class = nil, contents = nil
172
+ "<li#{%( class="#{css_class}") if css_class}>#{contents}</li>\n"
173
+ end
174
+
175
+ ##
176
+ # Uri for _page_. The following conversions are made
177
+ # to the _uri_ previously passed to #to_html:
178
+ #
179
+ # /items # Appends query string => /items?page=2
180
+ # /items?page=1 # Adjusts current page => /items?page=2
181
+ # /items?foo=bar # Appends page pair => /items?foo=bar&page=1
182
+ #
183
+
184
+ def uri_for page
185
+ case @uri
186
+ when /page=/ ; @uri.gsub /page=\d+/, "page=#{page}"
187
+ when /\?/ ; @uri += "&page=#{page}"
188
+ else ; @uri += "?page=#{page}"
189
+ end
190
+ end
191
+
192
+ end
193
+ end
@@ -0,0 +1,65 @@
1
+
2
+ module DataMapper
3
+ module Pagination
4
+
5
+ ##
6
+ # DataMapper::Pager instance.
7
+
8
+ attr_accessor :pager
9
+
10
+ ##
11
+ # Page collection by the _page_ number and _options_ provided.
12
+ #
13
+ # Since pagers will commonly be used with query strings, we
14
+ # coerce all numeric strings such as '12' to their integer value 12.
15
+ # This is the case for _page_, :per_page, :page, etc.
16
+ #
17
+ # === Options
18
+ #
19
+ # :page Current page number
20
+ # :per_page Results per page; defaults to 6
21
+ # :order Defaults to [:id.desc]
22
+ #
23
+ # === Examples
24
+ #
25
+ # User.all.page
26
+ # User.all.page(2)
27
+ # User.all.page(2, :per_page => 5)
28
+ # User.all.page(:page => 2, :per_page => 5)
29
+ #
30
+
31
+ def page page = nil, options = {}
32
+ options, page = page, nil if page.is_a? Hash
33
+ page ||= pager_option :page, options
34
+ options.delete :page
35
+ page = 1 unless (page = page.to_i) && page > 1
36
+ per_page = pager_option(:per_page, options).to_i
37
+ query = options.dup
38
+ collection = new_collection scoped_query(options = {
39
+ :limit => per_page,
40
+ :offset => (page - 1) * per_page,
41
+ :order => [:id.desc]
42
+ }.merge(query))
43
+ options.merge! :total => count(query), :page => page
44
+ collection.pager = DataMapper::Pager.new options
45
+ collection
46
+ end
47
+
48
+ private
49
+
50
+ ##
51
+ # Return value for _key_ from indifferent hash _options_.
52
+ #
53
+ # * Checks for sym key
54
+ # * Checks for string key
55
+ # * Checks DataMapper::Pagination.defaults for the sym key
56
+ # * Deletes both keys to prevent them from being part of the query
57
+ #
58
+
59
+ def pager_option key, options = {}
60
+ a = options.delete key.to_sym
61
+ b = options.delete key.to_s
62
+ a || b || Pagination.defaults[key.to_sym]
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,6 @@
1
+
2
+ module DataMapper
3
+ module Pagination
4
+ VERSION = '0.0.7'
5
+ end
6
+ end
data/lib/dm-pager.rb ADDED
@@ -0,0 +1,47 @@
1
+ #--
2
+ # Copyright (c) 2009 TJ Holowaychuk <tj@vision-media.ca>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ require 'dm-core'
25
+ require 'dm-aggregates'
26
+ require 'dm-pager/version'
27
+ require 'dm-pager/defaults'
28
+ require 'dm-pager/pagination'
29
+ require 'dm-pager/pager'
30
+ require 'dm-pager/helpers'
31
+
32
+ #--
33
+ # DataMapper
34
+ #++
35
+
36
+ DataMapper::Model.send :include, DataMapper::Pagination
37
+ DataMapper::Collection.send :include, DataMapper::Pagination
38
+ DataMapper::Query.send :include, DataMapper::Pagination
39
+
40
+ #--
41
+ # Rails
42
+ #++
43
+
44
+ if defined? ActionView::Base
45
+ ActionView::Base.send :include, DataMapper::Pagination::Helpers::Rails
46
+ end
47
+
@@ -0,0 +1,18 @@
1
+
2
+ require File.dirname(__FILE__) + '/../spec_helper'
3
+
4
+ describe DataMapper::Pagination::Helpers::Rails do
5
+ include DataMapper::Pagination::Helpers::Rails
6
+
7
+ describe '#paginate' do
8
+ before do
9
+ @collection = stub 'Collection', :pager => stub('Pager')
10
+ @template = stub 'Template', :path => 'path', :params => { :foo => :bar }, :url_for => '/projects/popular?page=3'
11
+ end
12
+
13
+ it "should invoke the pager's #to_html method'" do
14
+ @collection.pager.should_receive(:to_html).once.with('/projects/popular?page=3', {})
15
+ paginate(@collection)
16
+ end
17
+ end
18
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format specdoc
@@ -0,0 +1,25 @@
1
+
2
+ $:.unshift 'lib'
3
+ require 'rubygems'
4
+ require 'dm-core'
5
+ require 'dm-pager'
6
+
7
+ DataMapper.setup :default, 'sqlite3::memory:'
8
+
9
+ class Item
10
+ include DataMapper::Resource
11
+ property :id, Serial
12
+ end
13
+
14
+ def mock_items
15
+ DataMapper.auto_migrate!
16
+ 1.upto 20 do |n|
17
+ instance_variable_set :"@item_#{n}", Item.create
18
+ end
19
+ end
20
+
21
+ def items from, to
22
+ (from..to).map do |n|
23
+ instance_variable_get :"@item_#{n}"
24
+ end
25
+ end
@@ -0,0 +1,220 @@
1
+
2
+ require File.dirname(__FILE__) + '/../spec_helper'
3
+
4
+ describe DataMapper::Pager do
5
+ before(:each) { mock_items }
6
+
7
+ describe "#to_html" do
8
+ describe "when pages are available" do
9
+ it "should render a ul.pager wrapper" do
10
+ Item.page.pager.to_html('/').should match(/ul class="([^"]+)?"/)
11
+ end
12
+
13
+ it "should render a ul containing intermediate items" do
14
+ Item.page.pager.to_html('/').should match(/<ul class="[^"]+?"><li/)
15
+ end
16
+
17
+ it "should add the 'active' class to the current page link <li>" do
18
+ Item.page.pager.to_html('/').should include('li class="page-1 active"><a href="/?page=1"')
19
+ Item.page(2).pager.to_html('/').should include('li class="page-2 active"><a href="/?page=2"')
20
+ Item.page(3).pager.to_html('/').should include('li class="page-3 active"><a href="/?page=3"')
21
+ end
22
+
23
+ it "should add li.last.jump" do
24
+ Item.page.pager.to_html('/').should include('<li class="last jump">')
25
+ end
26
+
27
+ it "should add li.first.jump" do
28
+ Item.page(2).pager.to_html('/').should include('<li class="first jump"')
29
+ end
30
+
31
+ it "should add li.next.jump" do
32
+ Item.page.pager.to_html('/').should include('<li class="next jump">')
33
+ end
34
+
35
+ it "should add li.previous.jump" do
36
+ Item.page(2).pager.to_html('/').should include('<li class="previous jump">')
37
+ end
38
+ end
39
+
40
+ describe "when one page is available" do
41
+ it "should render nothing" do
42
+ Item.all(:id.lt => 2).page.pager.to_html('/').should be_nil
43
+ end
44
+ end
45
+
46
+ describe "when no pages are available" do
47
+ it "should render nothing" do
48
+ Item.all(:id.lt => 1).page.pager.to_html('/').should be_nil
49
+ end
50
+ end
51
+
52
+ describe "when on the first page" do
53
+ it "should not render the 'Previous' page link" do
54
+ markup = Item.page.pager.to_html('/')
55
+ markup.should_not include('Previous')
56
+ end
57
+
58
+ it "should render some intermediate page links with ... after" do
59
+ markup = Item.page.pager.to_html('/', :size => 3)
60
+ markup.should include('>1<')
61
+ markup.should include('>2<')
62
+ markup.should include('>3<')
63
+ markup.should_not include('>4<')
64
+ markup.should include(%(<li class="more">...</li>\n<li class="next jump"))
65
+ end
66
+
67
+ it "should not render ... before" do
68
+ markup = Item.page.pager.to_html('/', :size => 3)
69
+ markup.should_not include('<a href="/?page=3" class="previous jump">Previous</a><li class="more">...</li>')
70
+ end
71
+
72
+ it "should not render the 'First' page link" do
73
+ markup = Item.page.pager.to_html('/')
74
+ markup.should_not include('First')
75
+ end
76
+
77
+ it "should render the 'Last' page link" do
78
+ markup = Item.page.pager.to_html('/')
79
+ markup.should include('Last')
80
+ end
81
+ end
82
+
83
+ describe "with the :size option set" do
84
+ it "should raise an error when given an even number" do
85
+ lambda { Item.page.pager.to_html('/', :size => 2) }.should raise_error(ArgumentError, /must be an odd number/)
86
+ end
87
+
88
+ it "should render only the specified number of intermediate page links" do
89
+ markup = Item.page.pager.to_html('/', :size => 3)
90
+ markup.should include('>1<')
91
+ markup.should include('>2<')
92
+ markup.should include('>3<')
93
+ markup.should_not include('>4<')
94
+ end
95
+ end
96
+
97
+ [:first, :previous, :next, :last].each do |pos|
98
+ describe "with the #{pos.inspect} option set" do
99
+ it "should change the default contents for the '#{pos}' link" do
100
+ markup = Item.page(2, :per_page => 2).pager.to_html('/', :"#{pos}_text" => 'FOO')
101
+ markup.should include('>FOO<')
102
+ end
103
+ end
104
+ end
105
+
106
+ describe "when on the last page" do
107
+ it "should not render the 'Next' page link" do
108
+ markup = Item.page(4).pager.to_html('/')
109
+ markup.should_not include('Next')
110
+ end
111
+
112
+ it "should not render the 'Last' page link" do
113
+ markup = Item.page(4).pager.to_html('/')
114
+ markup.should_not include('Last')
115
+ end
116
+
117
+ it "should render the 'First' page link" do
118
+ markup = Item.page(4).pager.to_html('/')
119
+ markup.should include('First')
120
+ end
121
+
122
+ it "should render some intermediate page links with ... before" do
123
+ markup = Item.page(4).pager.to_html('/', :size => 3)
124
+ markup.should include(%(<li class="previous jump"><a href="/?page=3">Previous</a></li>\n<li class="more">...<))
125
+ markup.should_not include('>1<')
126
+ markup.should include('>2<')
127
+ markup.should include('>3<')
128
+ markup.should include('>4<')
129
+ markup.should_not include('>5<')
130
+ end
131
+
132
+ it "should not render ... after" do
133
+ markup = Item.page(4).pager.to_html('/', :size => 3)
134
+ markup.should_not include(%(<li class="more">...</li>\n<a href="/?page=6" class="next jump"))
135
+ end
136
+ end
137
+
138
+ describe "when on an intermediate page" do
139
+ it "should render the 'Previous' page link" do
140
+ markup = Item.page(2).pager.to_html('/')
141
+ markup.should include('Previous')
142
+ end
143
+
144
+ it "should render the 'Next' page link" do
145
+ markup = Item.page(2).pager.to_html('/')
146
+ markup.should include('Next')
147
+ end
148
+
149
+ it "should render some intermediate page links with ... before and after" do
150
+ markup = Item.page(5, :per_page => 2).pager.to_html('/', :size => 3)
151
+ markup.should include(%(<li class="previous jump"><a href="/?page=4">Previous</a></li>\n<li class="more">...</li>))
152
+ markup.should_not include('>3<')
153
+ markup.should include('>4<')
154
+ markup.should include('>5<')
155
+ markup.should include('>6<')
156
+ markup.should_not include('>7<')
157
+ markup.should include(%(<li class="more">...</li>\n<li class="next jump"))
158
+ end
159
+
160
+ it "should render the 'Last' page link" do
161
+ markup = Item.page(2).pager.to_html('/')
162
+ markup.should include('Last')
163
+ end
164
+
165
+ it "should render the 'First' page link" do
166
+ markup = Item.page(2).pager.to_html('/')
167
+ markup.should include('First')
168
+ end
169
+ end
170
+
171
+ describe "when on the second page" do
172
+ it "should render 1 through 3 when :size is 3 followed by ..." do
173
+ markup = Item.page(2, :per_page => 2).pager.to_html('/', :size => 3)
174
+ markup.should_not include('<ul><li class="more">...<')
175
+ markup.should include('>1<')
176
+ markup.should include('>2<')
177
+ markup.should include('>3<')
178
+ markup.should_not include('>4<')
179
+ markup.should include(%(<li class="more">...</li>\n<li class="next jump"))
180
+ end
181
+ end
182
+
183
+ describe "when on the second last page" do
184
+ it "should render 8 through 10 when :size is 3 with preceding ..." do
185
+ markup = Item.page(9, :per_page => 2).pager.to_html('/', :size => 3)
186
+ markup.should include(%(<li class="previous jump"><a href="/?page=8">Previous</a></li>\n<li class="more">...<))
187
+ markup.should_not include('>7<')
188
+ markup.should include('>8<')
189
+ markup.should include('>9<')
190
+ markup.should include('>10<')
191
+ markup.should_not include('>11<')
192
+ markup.should_not include(%(<li class="more">...</li>\n<li class="next jump"))
193
+ end
194
+ end
195
+
196
+ describe "when passing a uri without a query string" do
197
+ it "should append a query string to each uri" do
198
+ markup = Item.page.pager.to_html 'items'
199
+ markup.should include('items?page=1')
200
+ end
201
+ end
202
+
203
+ describe "when passing a uri with a query string" do
204
+ describe "containing page=N" do
205
+ it "should alter the page value" do
206
+ markup = Item.page.pager.to_html 'items?page=2'
207
+ markup.should include('items?page=1')
208
+ end
209
+ end
210
+
211
+ describe "not containing page=N" do
212
+ it "should append a pair" do
213
+ markup = Item.page.pager.to_html 'items?foo=bar'
214
+ markup.should include('items?foo=bar&page=1')
215
+ end
216
+ end
217
+ end
218
+
219
+ end
220
+ end
@@ -0,0 +1,141 @@
1
+
2
+ require File.dirname(__FILE__) + '/../spec_helper'
3
+
4
+ describe DataMapper::Pagination do
5
+ before(:each) { mock_items }
6
+
7
+ describe "#page" do
8
+ describe "given the page" do
9
+ it "return the appropriately sized collection" do
10
+ Item.page(1, :order => [:id.asc]).should == items(1, 6)
11
+ Item.page(2, :order => [:id.asc]).should == items(7, 12)
12
+ Item.page(3, :order => [:id.asc]).should == items(13, 18)
13
+ end
14
+
15
+ describe "number" do
16
+ it "should default to the first page" do
17
+ Item.page.pager.current_page.should == 1
18
+ end
19
+ end
20
+
21
+ describe "nil" do
22
+ it "should default to the first page" do
23
+ Item.page(nil).pager.current_page.should == 1
24
+ end
25
+ end
26
+
27
+ describe "number below 1" do
28
+ it "should default to the first page" do
29
+ Item.page(0).pager.current_page.should == 1
30
+ Item.page(-1).pager.current_page.should == 1
31
+ end
32
+ end
33
+
34
+ describe "string" do
35
+ it "should be coerced to ints" do
36
+ Item.page('5').pager.current_page.should == 5
37
+ Item.page('5.0').pager.current_page.should == 5
38
+ Item.page('-1').pager.current_page.should == 1
39
+ end
40
+
41
+ describe "which is not numeric" do
42
+ it "should default to the first page" do
43
+ Item.page('wahoo').pager.current_page.should == 1
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "of an arbitrary object" do
49
+ it "should raise an error unless responding to #to_i" do
50
+ lambda { Item.page(true) }.should raise_error
51
+ end
52
+ end
53
+ end
54
+
55
+ describe "options hash" do
56
+ it "should be accepted as first param" do
57
+ Item.page(:page => 2, :order => [:id.asc]).pager.current_page.should == 2
58
+ end
59
+
60
+ it "should be accepted as second param" do
61
+ Item.page(3, :page => 2, :order => [:id.asc]).pager.current_page.should == 3
62
+ end
63
+ end
64
+
65
+ describe "option" do
66
+ describe ":per_page" do
67
+ it "should default to 6" do
68
+ Item.page.length.should == 6
69
+ end
70
+
71
+ it "should be allow an alternate value" do
72
+ Item.page(1, :per_page => 3, :order => [:id.asc]).should == items(1, 3)
73
+ Item.page(2, :per_page => 3, :order => [:id.asc]).should == items(4, 6)
74
+ Item.page(3, :per_page => 3, :order => [:id.asc]).should == items(7, 9)
75
+ end
76
+
77
+ it "should allow numeric strings" do
78
+ Item.page(1, :per_page => '3', :order => [:id.asc]).should == items(1, 3)
79
+ Item.page(2, :per_page => '3', :order => [:id.asc]).should == items(4, 6)
80
+ Item.page(3, :per_page => '3', :order => [:id.asc]).should == items(7, 9)
81
+ Item.page(3, :per_page => '3', :order => [:id.asc]).pager.per_page.should == 3
82
+ end
83
+
84
+ it "should delete keys when an indifferent hash is passed" do
85
+ Item.page(1, 'per_page' => '3', :order => [:id.asc]).should == items(1, 3)
86
+ Item.page(2, 'per_page' => '3', :order => [:id.asc]).should == items(4, 6)
87
+ Item.page(3, 'per_page' => '3', :order => [:id.asc]).should == items(7, 9)
88
+ Item.page(3, 'per_page' => '3', :order => [:id.asc]).pager.per_page.should == 3
89
+ end
90
+ end
91
+
92
+ describe ":order" do
93
+ it "should default to [:id.desc]" do
94
+ Item.page.should == items(15, 20).reverse
95
+ end
96
+ end
97
+
98
+ describe ":page" do
99
+ it "should raise an error unless responding to #to_i" do
100
+ lambda { Item.page(:page => true) }.should raise_error
101
+ lambda { Item.page('page' => true) }.should raise_error
102
+ end
103
+
104
+ it "should delete keys when an indifferent hash is passed" do
105
+ Item.page(:page => '2', 'page' => '2', :order => [:id.asc]).should == items(7, 12)
106
+ Item.page(:page => '2', 'page' => '2', :order => [:id.asc]).pager.current_page.should == 2
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ describe "#pager" do
113
+ describe "#total" do
114
+ it "should be assigned when paging" do
115
+ Item.all.page.length.should == 6
116
+ Item.all.page.pager.total.should == 20
117
+ end
118
+ end
119
+
120
+ describe "#per_page" do
121
+ it "should be assigned when paging" do
122
+ Item.all.page.pager.per_page.should == 6
123
+ end
124
+ end
125
+
126
+ describe "#current_page" do
127
+ it "should be assigned when paging" do
128
+ Item.all.page.pager.current_page.should == 1
129
+ Item.all.page(3).pager.current_page.should == 3
130
+ end
131
+ end
132
+
133
+ describe "#total_pages" do
134
+ it "should be assigned when paging" do
135
+ Item.all.page.pager.total_pages.should == 4
136
+ Item.all.page(:per_page => 3).pager.total_pages.should == 7
137
+ Item.all.page(:per_page => 2).pager.total_pages.should == 10
138
+ end
139
+ end
140
+ end
141
+ end
data/tasks/docs.rake ADDED
@@ -0,0 +1,13 @@
1
+
2
+ namespace :docs do
3
+
4
+ desc 'Remove rdoc products'
5
+ task :remove => [:clobber_docs]
6
+
7
+ desc 'Build docs, and open in browser for viewing (specify BROWSER)'
8
+ task :open do
9
+ browser = ENV["BROWSER"] || "safari"
10
+ sh "open -a #{browser} doc/index.html"
11
+ end
12
+
13
+ end
@@ -0,0 +1,3 @@
1
+
2
+ desc 'Build gemspec file'
3
+ task :gemspec => [:build_gemspec]
data/tasks/spec.rake ADDED
@@ -0,0 +1,25 @@
1
+
2
+ require 'spec/rake/spectask'
3
+
4
+ desc "Run all specifications"
5
+ Spec::Rake::SpecTask.new(:spec) do |t|
6
+ t.libs << "lib"
7
+ t.spec_opts = ["--color", "--require", "spec/spec_helper.rb"]
8
+ end
9
+
10
+ namespace :spec do
11
+
12
+ desc "Run all specifications verbosely"
13
+ Spec::Rake::SpecTask.new(:verbose) do |t|
14
+ t.libs << "lib"
15
+ t.spec_opts = ["--color", "--format", "specdoc", "--require", "spec/spec_helper.rb"]
16
+ end
17
+
18
+ desc "Run specific specification verbosely (specify SPEC)"
19
+ Spec::Rake::SpecTask.new(:select) do |t|
20
+ t.libs << "lib"
21
+ t.spec_files = [ENV["SPEC"]]
22
+ t.spec_opts = ["--color", "--format", "specdoc", "--require", "spec/spec_helper.rb"]
23
+ end
24
+
25
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dm-pager
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.7
5
+ platform: ruby
6
+ authors:
7
+ - TJ Holowaychuk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-10 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: dm-core
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.10.1
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: dm-aggregates
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.10.1
34
+ version:
35
+ description: DataMapper Pagination
36
+ email: tj@vision-media.ca
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - lib/dm-pager.rb
43
+ - lib/dm-pager/defaults.rb
44
+ - lib/dm-pager/helpers.rb
45
+ - lib/dm-pager/helpers/rails.rb
46
+ - lib/dm-pager/pager.rb
47
+ - lib/dm-pager/pagination.rb
48
+ - lib/dm-pager/version.rb
49
+ - tasks/docs.rake
50
+ - tasks/gemspec.rake
51
+ - tasks/spec.rake
52
+ files:
53
+ - History.md
54
+ - Manifest
55
+ - Rakefile
56
+ - Readme.md
57
+ - examples/pager.rb
58
+ - lib/dm-pager.rb
59
+ - lib/dm-pager/defaults.rb
60
+ - lib/dm-pager/helpers.rb
61
+ - lib/dm-pager/helpers/rails.rb
62
+ - lib/dm-pager/pager.rb
63
+ - lib/dm-pager/pagination.rb
64
+ - lib/dm-pager/version.rb
65
+ - spec/integration/rails_helper_spec.rb
66
+ - spec/spec.opts
67
+ - spec/spec_helper.rb
68
+ - spec/unit/pager_spec.rb
69
+ - spec/unit/pagination_spec.rb
70
+ - tasks/docs.rake
71
+ - tasks/gemspec.rake
72
+ - tasks/spec.rake
73
+ - dm-pager.gemspec
74
+ has_rdoc: true
75
+ homepage: http://github.com/visionmedia/dm-pagination
76
+ licenses: []
77
+
78
+ post_install_message:
79
+ rdoc_options:
80
+ - --line-numbers
81
+ - --inline-source
82
+ - --title
83
+ - Dm-pager
84
+ - --main
85
+ - Readme.md
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: "0"
93
+ version:
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: "1.2"
99
+ version:
100
+ requirements: []
101
+
102
+ rubyforge_project: dm-pager
103
+ rubygems_version: 1.3.5
104
+ signing_key:
105
+ specification_version: 3
106
+ summary: DataMapper Pagination
107
+ test_files: []
108
+