dm-pager 0.0.7

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/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
+