classic_pagination 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e3fbc1fb4a82e59609b893e20e5bd35950faff89ea570e2fa89f7a3bf8347527
4
- data.tar.gz: 96ba291c2f03bcf85a5a61eccd1cb6860cb22e9ff379d5eb21d3f1727dfb14d6
3
+ metadata.gz: f3b03fd55045c78443d4a9442c08fad881e56e3ed1607f11890e7ece41f7b727
4
+ data.tar.gz: 37ed62c09e37bedc7e16161a3a0078403b46005ee741093bdf06d7e311ab53e9
5
5
  SHA512:
6
- metadata.gz: cafe2a37a168670f5fb3ecdfed2cc7f77256a7ff7404b11a9af172e1be417ccfe939ce36de23015711097982ebb7108761f84e4cdcaf8fc69980e89c4b518e22
7
- data.tar.gz: 820dcac72b59b4d45014f22b6cbc5bbe284ae5f477fe7804a793eef9c51e95eb2820154264cff78b239b521c70ed21fe74eae0d115860d063900555371262544
6
+ metadata.gz: a9bb76e3f4b45fb477132e5f1e70367ca51fcf9be94ed32f2a6c130656fd745004195a36715b63cc363ad27592164474cb550f7fa4cd1b471bd94731eabcd23c
7
+ data.tar.gz: 72f76dfc9ea1d097940ac05e1dc22333e14d2301992a138381742330418f7bad07c5e3fa26c4105d69764346b8c6974c60d9ddaf25fbffa1a4f51ca64d7741fa
data/CHANGELOG ADDED
@@ -0,0 +1,152 @@
1
+ * Exported the changelog of Pagination code for historical reference.
2
+
3
+ * Imported some patches from Rails Trac (others closed as "wontfix"):
4
+ #8176, #7325, #7028, #4113. Documentation is much cleaner now and there
5
+ are some new unobtrusive features!
6
+
7
+ * Extracted Pagination from Rails trunk (r6795)
8
+
9
+ #
10
+ # ChangeLog for /trunk/actionpack/lib/action_controller/pagination.rb
11
+ #
12
+ # Generated by Trac 0.10.3
13
+ # 05/20/07 23:48:02
14
+ #
15
+
16
+ 09/03/06 23:28:54 david [4953]
17
+ * trunk/actionpack/lib/action_controller/pagination.rb (modified)
18
+ Docs and deprecation
19
+
20
+ 08/07/06 12:40:14 bitsweat [4715]
21
+ * trunk/actionpack/lib/action_controller/pagination.rb (modified)
22
+ Deprecate direct usage of @params. Update ActionView::Base for
23
+ instance var deprecation.
24
+
25
+ 06/21/06 02:16:11 rick [4476]
26
+ * trunk/actionpack/lib/action_controller/pagination.rb (modified)
27
+ Fix indent in pagination documentation. Closes #4990. [Kevin Clark]
28
+
29
+ 04/25/06 17:42:48 marcel [4268]
30
+ * trunk/actionpack/lib/action_controller/pagination.rb (modified)
31
+ Remove all remaining references to @params in the documentation.
32
+
33
+ 03/16/06 06:38:08 rick [3899]
34
+ * trunk/actionpack/lib/action_view/helpers/pagination_helper.rb (modified)
35
+ trivial documentation patch for #pagination_links [Francois
36
+ Beausoleil] closes #4258
37
+
38
+ 02/20/06 03:15:22 david [3620]
39
+ * trunk/actionpack/lib/action_controller/pagination.rb (modified)
40
+ * trunk/actionpack/test/activerecord/pagination_test.rb (modified)
41
+ * trunk/activerecord/CHANGELOG (modified)
42
+ * trunk/activerecord/lib/active_record/base.rb (modified)
43
+ * trunk/activerecord/test/base_test.rb (modified)
44
+ Added :count option to pagination that'll make it possible for the
45
+ ActiveRecord::Base.count call to using something else than * for the
46
+ count. Especially important for count queries using DISTINCT #3839
47
+ [skaes]. Added :select option to Base.count that'll allow you to
48
+ select something else than * to be counted on. Especially important
49
+ for count queries using DISTINCT (closes #3839) [skaes].
50
+
51
+ 02/09/06 09:17:40 nzkoz [3553]
52
+ * trunk/actionpack/lib/action_controller/pagination.rb (modified)
53
+ * trunk/actionpack/test/active_record_unit.rb (added)
54
+ * trunk/actionpack/test/activerecord (added)
55
+ * trunk/actionpack/test/activerecord/active_record_assertions_test.rb (added)
56
+ * trunk/actionpack/test/activerecord/pagination_test.rb (added)
57
+ * trunk/actionpack/test/controller/active_record_assertions_test.rb (deleted)
58
+ * trunk/actionpack/test/fixtures/companies.yml (added)
59
+ * trunk/actionpack/test/fixtures/company.rb (added)
60
+ * trunk/actionpack/test/fixtures/db_definitions (added)
61
+ * trunk/actionpack/test/fixtures/db_definitions/sqlite.sql (added)
62
+ * trunk/actionpack/test/fixtures/developer.rb (added)
63
+ * trunk/actionpack/test/fixtures/developers_projects.yml (added)
64
+ * trunk/actionpack/test/fixtures/developers.yml (added)
65
+ * trunk/actionpack/test/fixtures/project.rb (added)
66
+ * trunk/actionpack/test/fixtures/projects.yml (added)
67
+ * trunk/actionpack/test/fixtures/replies.yml (added)
68
+ * trunk/actionpack/test/fixtures/reply.rb (added)
69
+ * trunk/actionpack/test/fixtures/topic.rb (added)
70
+ * trunk/actionpack/test/fixtures/topics.yml (added)
71
+ * Fix pagination problems when using include
72
+ * Introduce Unit Tests for pagination
73
+ * Allow count to work with :include by using count distinct.
74
+
75
+ [Kevin Clark & Jeremy Hopple]
76
+
77
+ 11/05/05 02:10:29 bitsweat [2878]
78
+ * trunk/actionpack/lib/action_controller/pagination.rb (modified)
79
+ Update paginator docs. Closes #2744.
80
+
81
+ 10/16/05 15:42:03 minam [2649]
82
+ * trunk/actionpack/lib/action_controller/pagination.rb (modified)
83
+ Update/clean up AP documentation (rdoc)
84
+
85
+ 08/31/05 00:13:10 ulysses [2078]
86
+ * trunk/actionpack/CHANGELOG (modified)
87
+ * trunk/actionpack/lib/action_controller/pagination.rb (modified)
88
+ Add option to specify the singular name used by pagination. Closes
89
+ #1960
90
+
91
+ 08/23/05 14:24:15 minam [2041]
92
+ * trunk/actionpack/CHANGELOG (modified)
93
+ * trunk/actionpack/lib/action_controller/pagination.rb (modified)
94
+ Add support for :include with pagination (subject to existing
95
+ constraints for :include with :limit and :offset) #1478
96
+ [michael@schubert.cx]
97
+
98
+ 07/15/05 20:27:38 david [1839]
99
+ * trunk/actionpack/lib/action_controller/pagination.rb (modified)
100
+ * trunk/actionpack/lib/action_view/helpers/pagination_helper.rb (modified)
101
+ More pagination speed #1334 [Stefan Kaes]
102
+
103
+ 07/14/05 08:02:01 david [1832]
104
+ * trunk/actionpack/lib/action_controller/pagination.rb (modified)
105
+ * trunk/actionpack/lib/action_view/helpers/pagination_helper.rb (modified)
106
+ * trunk/actionpack/test/controller/addresses_render_test.rb (modified)
107
+ Made pagination faster #1334 [Stefan Kaes]
108
+
109
+ 04/13/05 05:40:22 david [1159]
110
+ * trunk/actionpack/CHANGELOG (modified)
111
+ * trunk/actionpack/lib/action_controller/pagination.rb (modified)
112
+ * trunk/activerecord/lib/active_record/base.rb (modified)
113
+ Fixed pagination to work with joins #1034 [scott@sigkill.org]
114
+
115
+ 04/02/05 09:11:17 david [1067]
116
+ * trunk/actionpack/CHANGELOG (modified)
117
+ * trunk/actionpack/lib/action_controller/pagination.rb (modified)
118
+ * trunk/actionpack/lib/action_controller/scaffolding.rb (modified)
119
+ * trunk/actionpack/lib/action_controller/templates/scaffolds/list.rhtml (modified)
120
+ * trunk/railties/lib/rails_generator/generators/components/scaffold/templates/controller.rb (modified)
121
+ * trunk/railties/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml (modified)
122
+ Added pagination for scaffolding (10 items per page) #964
123
+ [mortonda@dgrmm.net]
124
+
125
+ 03/31/05 14:46:11 david [1048]
126
+ * trunk/actionpack/lib/action_view/helpers/pagination_helper.rb (modified)
127
+ Improved the message display on the exception handler pages #963
128
+ [Johan Sorensen]
129
+
130
+ 03/27/05 00:04:07 david [1017]
131
+ * trunk/actionpack/CHANGELOG (modified)
132
+ * trunk/actionpack/lib/action_view/helpers/pagination_helper.rb (modified)
133
+ Fixed that pagination_helper would ignore :params #947 [Sebastian
134
+ Kanthak]
135
+
136
+ 03/22/05 13:09:44 david [976]
137
+ * trunk/actionpack/lib/action_view/helpers/pagination_helper.rb (modified)
138
+ Fixed documentation and prepared for 0.11.0 release
139
+
140
+ 03/21/05 14:35:36 david [967]
141
+ * trunk/actionpack/lib/action_controller/pagination.rb (modified)
142
+ * trunk/actionpack/lib/action_view/helpers/pagination_helper.rb (modified)
143
+ Tweaked the documentation
144
+
145
+ 03/20/05 23:12:05 david [949]
146
+ * trunk/actionpack/CHANGELOG (modified)
147
+ * trunk/actionpack/lib/action_controller.rb (modified)
148
+ * trunk/actionpack/lib/action_controller/pagination.rb (added)
149
+ * trunk/actionpack/lib/action_view/helpers/pagination_helper.rb (added)
150
+ * trunk/activesupport/lib/active_support/core_ext/kernel.rb (added)
151
+ Added pagination support through both a controller and helper add-on
152
+ #817 [Sam Stephenson]
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,25 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ classic_pagination (1.0.2)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ power_assert (2.0.1)
10
+ rake (0.9.6)
11
+ test-unit (3.5.3)
12
+ power_assert
13
+
14
+ PLATFORMS
15
+ ruby
16
+ x86_64-darwin-21
17
+
18
+ DEPENDENCIES
19
+ bundler (= 2.1.4)
20
+ classic_pagination!
21
+ rake (~> 0.9.2)
22
+ test-unit (= 3.5.3)
23
+
24
+ BUNDLED WITH
25
+ 2.2.32
data/README ADDED
@@ -0,0 +1,18 @@
1
+ Pagination
2
+ ==========
3
+
4
+ To install:
5
+
6
+ script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination
7
+
8
+ This code was extracted from Rails trunk after the release 1.2.3.
9
+ WARNING: this code is dead. It is unmaintained, untested and full of cruft.
10
+
11
+ There is a much better pagination plugin called will_paginate.
12
+ Install it like this and glance through the README:
13
+
14
+ script/plugin install svn://errtheblog.com/svn/plugins/will_paginate
15
+
16
+ It doesn't have the same API, but is in fact much nicer. You can
17
+ have both plugins installed until you change your controller/view code that
18
+ handles pagination. Then, simply uninstall classic_pagination.
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the classic_pagination plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the classic_pagination plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'Pagination'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
@@ -0,0 +1,20 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'classic_pagination'
3
+ s.version = '1.0.3'
4
+ s.summary = 'A pagination gem'
5
+ s.description = 'A pagination gem'
6
+ s.authors = ['sachinsinghcdn']
7
+ s.email = ['sachinsingh@poweron.com']
8
+ s.files = `git ls-files`.split("\n").sort
9
+ s.require_paths = ['lib']
10
+ s.homepage = 'https://github.com/poweronservices/classic_pagination'
11
+ s.license = 'MIT'
12
+
13
+ s.add_development_dependency 'rake', '~> 0.9.2'
14
+ s.add_development_dependency 'bundler', '2.1.4'
15
+ s.add_development_dependency 'test-unit', '3.5.3'
16
+
17
+ s.add_runtime_dependency 'rails', '~> 2.3.18'
18
+ s.add_runtime_dependency 'actionpack', '~> 2.3.18'
19
+ s.add_runtime_dependency 'activesupport', '~> 2.3.18'
20
+ end
@@ -21,8 +21,11 @@
21
21
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  #++
23
23
 
24
- require 'pagination'
25
- require 'pagination_helper'
24
+ require 'yaml'
25
+ require 'active_support'
26
+ require 'actionpack'
27
+ require_relative 'pagination'
28
+ require_relative 'pagination_helper'
26
29
 
27
30
  ActionController::Base.class_eval do
28
31
  include ActionController::Pagination
data/lib/pagination.rb ADDED
@@ -0,0 +1,405 @@
1
+ module ActionController
2
+ # === Action Pack pagination for Active Record collections
3
+ #
4
+ # The Pagination module aids in the process of paging large collections of
5
+ # Active Record objects. It offers macro-style automatic fetching of your
6
+ # model for multiple views, or explicit fetching for single actions. And if
7
+ # the magic isn't flexible enough for your needs, you can create your own
8
+ # paginators with a minimal amount of code.
9
+ #
10
+ # The Pagination module can handle as much or as little as you wish. In the
11
+ # controller, have it automatically query your model for pagination; or,
12
+ # if you prefer, create Paginator objects yourself.
13
+ #
14
+ # Pagination is included automatically for all controllers.
15
+ #
16
+ # For help rendering pagination links, see
17
+ # ActionView::Helpers::PaginationHelper.
18
+ #
19
+ # ==== Automatic pagination for every action in a controller
20
+ #
21
+ # class PersonController < ApplicationController
22
+ # model :person
23
+ #
24
+ # paginate :people, :order => 'last_name, first_name',
25
+ # :per_page => 20
26
+ #
27
+ # # ...
28
+ # end
29
+ #
30
+ # Each action in this controller now has access to a <tt>@people</tt>
31
+ # instance variable, which is an ordered collection of model objects for the
32
+ # current page (at most 20, sorted by last name and first name), and a
33
+ # <tt>@person_pages</tt> Paginator instance. The current page is determined
34
+ # by the <tt>params[:page]</tt> variable.
35
+ #
36
+ # ==== Pagination for a single action
37
+ #
38
+ # def list
39
+ # @person_pages, @people =
40
+ # paginate :people, :order => 'last_name, first_name'
41
+ # end
42
+ #
43
+ # Like the previous example, but explicitly creates <tt>@person_pages</tt>
44
+ # and <tt>@people</tt> for a single action, and uses the default of 10 items
45
+ # per page.
46
+ #
47
+ # ==== Custom/"classic" pagination
48
+ #
49
+ # def list
50
+ # @person_pages = Paginator.new self, Person.count, 10, params[:page]
51
+ # @people = Person.find :all, :order => 'last_name, first_name',
52
+ # :limit => @person_pages.items_per_page,
53
+ # :offset => @person_pages.current.offset
54
+ # end
55
+ #
56
+ # Explicitly creates the paginator from the previous example and uses
57
+ # Paginator#to_sql to retrieve <tt>@people</tt> from the model.
58
+ #
59
+ module Pagination
60
+ unless const_defined?(:OPTIONS)
61
+ # A hash holding options for controllers using macro-style pagination
62
+ OPTIONS = Hash.new
63
+
64
+ # The default options for pagination
65
+ DEFAULT_OPTIONS = {
66
+ :class_name => nil,
67
+ :singular_name => nil,
68
+ :per_page => 10,
69
+ :conditions => nil,
70
+ :order_by => nil,
71
+ :order => nil,
72
+ :join => nil,
73
+ :joins => nil,
74
+ :count => nil,
75
+ :include => nil,
76
+ :select => nil,
77
+ :group => nil,
78
+ :parameter => 'page'
79
+ }
80
+ else
81
+ DEFAULT_OPTIONS[:group] = nil
82
+ end
83
+
84
+ def self.included(base) #:nodoc:
85
+ super
86
+ base.extend(ClassMethods)
87
+ end
88
+
89
+ def self.validate_options!(collection_id, options, in_action) #:nodoc:
90
+ options.merge!(DEFAULT_OPTIONS) {|key, old, new| old}
91
+
92
+ valid_options = DEFAULT_OPTIONS.keys
93
+ valid_options << :actions unless in_action
94
+
95
+ unknown_option_keys = options.keys - valid_options
96
+ raise ActionController::ActionControllerError,
97
+ "Unknown options: #{unknown_option_keys.join(', ')}" unless
98
+ unknown_option_keys.empty?
99
+
100
+ options[:singular_name] ||= ActiveSupport::Inflector.singularize(collection_id.to_s)
101
+ options[:class_name] ||= ActiveSupport::Inflector.camelize(options[:singular_name])
102
+ end
103
+
104
+ # Returns a paginator and a collection of Active Record model instances
105
+ # for the paginator's current page. This is designed to be used in a
106
+ # single action; to automatically paginate multiple actions, consider
107
+ # ClassMethods#paginate.
108
+ #
109
+ # +options+ are:
110
+ # <tt>:singular_name</tt>:: the singular name to use, if it can't be inferred by singularizing the collection name
111
+ # <tt>:class_name</tt>:: the class name to use, if it can't be inferred by
112
+ # camelizing the singular name
113
+ # <tt>:per_page</tt>:: the maximum number of items to include in a
114
+ # single page. Defaults to 10
115
+ # <tt>:conditions</tt>:: optional conditions passed to Model.find(:all, *params) and
116
+ # Model.count
117
+ # <tt>:order</tt>:: optional order parameter passed to Model.find(:all, *params)
118
+ # <tt>:order_by</tt>:: (deprecated, used :order) optional order parameter passed to Model.find(:all, *params)
119
+ # <tt>:joins</tt>:: optional joins parameter passed to Model.find(:all, *params)
120
+ # and Model.count
121
+ # <tt>:join</tt>:: (deprecated, used :joins or :include) optional join parameter passed to Model.find(:all, *params)
122
+ # and Model.count
123
+ # <tt>:include</tt>:: optional eager loading parameter passed to Model.find(:all, *params)
124
+ # and Model.count
125
+ # <tt>:select</tt>:: :select parameter passed to Model.find(:all, *params)
126
+ #
127
+ # <tt>:count</tt>:: parameter passed as :select option to Model.count(*params)
128
+ #
129
+ # <tt>:group</tt>:: :group parameter passed to Model.find(:all, *params). It forces the use of DISTINCT instead of plain COUNT to come up with the total number of records
130
+ #
131
+ def paginate(collection_id, options={})
132
+ Pagination.validate_options!(collection_id, options, true)
133
+ paginator_and_collection_for(collection_id, options)
134
+ end
135
+
136
+ # These methods become class methods on any controller
137
+ module ClassMethods
138
+ # Creates a +before_filter+ which automatically paginates an Active
139
+ # Record model for all actions in a controller (or certain actions if
140
+ # specified with the <tt>:actions</tt> option).
141
+ #
142
+ # +options+ are the same as PaginationHelper#paginate, with the addition
143
+ # of:
144
+ # <tt>:actions</tt>:: an array of actions for which the pagination is
145
+ # active. Defaults to +nil+ (i.e., every action)
146
+ def paginate(collection_id, options={})
147
+ Pagination.validate_options!(collection_id, options, false)
148
+ module_eval do
149
+ before_filter :create_paginators_and_retrieve_collections
150
+ OPTIONS[self] ||= Hash.new
151
+ OPTIONS[self][collection_id] = options
152
+ end
153
+ end
154
+ end
155
+
156
+ def create_paginators_and_retrieve_collections #:nodoc:
157
+ Pagination::OPTIONS[self.class].each do |collection_id, options|
158
+ next unless options[:actions].include? action_name if
159
+ options[:actions]
160
+
161
+ paginator, collection =
162
+ paginator_and_collection_for(collection_id, options)
163
+
164
+ paginator_name = "@#{options[:singular_name]}_pages"
165
+ self.instance_variable_set(paginator_name, paginator)
166
+
167
+ collection_name = "@#{collection_id.to_s}"
168
+ self.instance_variable_set(collection_name, collection)
169
+ end
170
+ end
171
+
172
+ # Returns the total number of items in the collection to be paginated for
173
+ # the +model+ and given +conditions+. Override this method to implement a
174
+ # custom counter.
175
+ def count_collection_for_pagination(model, options)
176
+ model.count(:conditions => options[:conditions],
177
+ :joins => options[:join] || options[:joins],
178
+ :include => options[:include],
179
+ :select => (options[:group] ? "DISTINCT #{options[:group]}" : options[:count]))
180
+ end
181
+
182
+ # Returns a collection of items for the given +model+ and +options[conditions]+,
183
+ # ordered by +options[order]+, for the current page in the given +paginator+.
184
+ # Override this method to implement a custom finder.
185
+ def find_collection_for_pagination(model, options, paginator)
186
+ model.find(:all, :conditions => options[:conditions],
187
+ :order => options[:order_by] || options[:order],
188
+ :joins => options[:join] || options[:joins], :include => options[:include],
189
+ :select => options[:select], :limit => options[:per_page],
190
+ :group => options[:group], :offset => paginator.current.offset)
191
+ end
192
+
193
+ protected :create_paginators_and_retrieve_collections,
194
+ :count_collection_for_pagination,
195
+ :find_collection_for_pagination
196
+
197
+ def paginator_and_collection_for(collection_id, options) #:nodoc:
198
+ klass = options[:class_name].constantize
199
+ page = params[options[:parameter]]
200
+ count = count_collection_for_pagination(klass, options)
201
+ paginator = Paginator.new(self, count, options[:per_page], page)
202
+ collection = find_collection_for_pagination(klass, options, paginator)
203
+
204
+ return paginator, collection
205
+ end
206
+
207
+ private :paginator_and_collection_for
208
+
209
+ # A class representing a paginator for an Active Record collection.
210
+ class Paginator
211
+ include Enumerable
212
+
213
+ # Creates a new Paginator on the given +controller+ for a set of items
214
+ # of size +item_count+ and having +items_per_page+ items per page.
215
+ # Raises ArgumentError if items_per_page is out of bounds (i.e., less
216
+ # than or equal to zero). The page CGI parameter for links defaults to
217
+ # "page" and can be overridden with +page_parameter+.
218
+ def initialize(controller, item_count, items_per_page, current_page=1)
219
+ raise ArgumentError, 'must have at least one item per page' if
220
+ items_per_page <= 0
221
+
222
+ @controller = controller
223
+ @item_count = item_count || 0
224
+ @items_per_page = items_per_page
225
+ @pages = {}
226
+
227
+ self.current_page = current_page
228
+ end
229
+ attr_reader :controller, :item_count, :items_per_page
230
+
231
+ # Sets the current page number of this paginator. If +page+ is a Page
232
+ # object, its +number+ attribute is used as the value; if the page does
233
+ # not belong to this Paginator, an ArgumentError is raised.
234
+ def current_page=(page)
235
+ if page.is_a? Page
236
+ raise ArgumentError, 'Page/Paginator mismatch' unless
237
+ page.paginator == self
238
+ end
239
+ page = page.to_i
240
+ @current_page_number = has_page_number?(page) ? page : 1
241
+ end
242
+
243
+ # Returns a Page object representing this paginator's current page.
244
+ def current_page
245
+ @current_page ||= self[@current_page_number]
246
+ end
247
+ alias current :current_page
248
+
249
+ # Returns a new Page representing the first page in this paginator.
250
+ def first_page
251
+ @first_page ||= self[1]
252
+ end
253
+ alias first :first_page
254
+
255
+ # Returns a new Page representing the last page in this paginator.
256
+ def last_page
257
+ @last_page ||= self[page_count]
258
+ end
259
+ alias last :last_page
260
+
261
+ # Returns the number of pages in this paginator.
262
+ def page_count
263
+ @page_count ||= @item_count.zero? ? 1 :
264
+ (q,r=@item_count.divmod(@items_per_page); r==0? q : q+1)
265
+ end
266
+
267
+ alias length :page_count
268
+
269
+ # Returns true if this paginator contains the page of index +number+.
270
+ def has_page_number?(number)
271
+ number >= 1 and number <= page_count
272
+ end
273
+
274
+ # Returns a new Page representing the page with the given index
275
+ # +number+.
276
+ def [](number)
277
+ @pages[number] ||= Page.new(self, number)
278
+ end
279
+
280
+ # Successively yields all the paginator's pages to the given block.
281
+ def each(&block)
282
+ page_count.times do |n|
283
+ yield self[n+1]
284
+ end
285
+ end
286
+
287
+ # A class representing a single page in a paginator.
288
+ class Page
289
+ include Comparable
290
+
291
+ # Creates a new Page for the given +paginator+ with the index
292
+ # +number+. If +number+ is not in the range of valid page numbers or
293
+ # is not a number at all, it defaults to 1.
294
+ def initialize(paginator, number)
295
+ @paginator = paginator
296
+ @number = number.to_i
297
+ @number = 1 unless @paginator.has_page_number? @number
298
+ end
299
+ attr_reader :paginator, :number
300
+ alias to_i :number
301
+
302
+ # Compares two Page objects and returns true when they represent the
303
+ # same page (i.e., their paginators are the same and they have the
304
+ # same page number).
305
+ def ==(page)
306
+ return false if page.nil?
307
+ @paginator == page.paginator and
308
+ @number == page.number
309
+ end
310
+
311
+ # Compares two Page objects and returns -1 if the left-hand page comes
312
+ # before the right-hand page, 0 if the pages are equal, and 1 if the
313
+ # left-hand page comes after the right-hand page. Raises ArgumentError
314
+ # if the pages do not belong to the same Paginator object.
315
+ def <=>(page)
316
+ raise ArgumentError unless @paginator == page.paginator
317
+ @number <=> page.number
318
+ end
319
+
320
+ # Returns the item offset for the first item in this page.
321
+ def offset
322
+ @paginator.items_per_page * (@number - 1)
323
+ end
324
+
325
+ # Returns the number of the first item displayed.
326
+ def first_item
327
+ offset + 1
328
+ end
329
+
330
+ # Returns the number of the last item displayed.
331
+ def last_item
332
+ [@paginator.items_per_page * @number, @paginator.item_count].min
333
+ end
334
+
335
+ # Returns true if this page is the first page in the paginator.
336
+ def first?
337
+ self == @paginator.first
338
+ end
339
+
340
+ # Returns true if this page is the last page in the paginator.
341
+ def last?
342
+ self == @paginator.last
343
+ end
344
+
345
+ # Returns a new Page object representing the page just before this
346
+ # page, or nil if this is the first page.
347
+ def previous
348
+ if first? then nil else @paginator[@number - 1] end
349
+ end
350
+
351
+ # Returns a new Page object representing the page just after this
352
+ # page, or nil if this is the last page.
353
+ def next
354
+ if last? then nil else @paginator[@number + 1] end
355
+ end
356
+
357
+ # Returns a new Window object for this page with the specified
358
+ # +padding+.
359
+ def window(padding=2)
360
+ Window.new(self, padding)
361
+ end
362
+
363
+ # Returns the limit/offset array for this page.
364
+ def to_sql
365
+ [@paginator.items_per_page, offset]
366
+ end
367
+
368
+ def to_param #:nodoc:
369
+ @number.to_s
370
+ end
371
+ end
372
+
373
+ # A class for representing ranges around a given page.
374
+ class Window
375
+ # Creates a new Window object for the given +page+ with the specified
376
+ # +padding+.
377
+ def initialize(page, padding=2)
378
+ @paginator = page.paginator
379
+ @page = page
380
+ self.padding = padding
381
+ end
382
+ attr_reader :paginator, :page
383
+
384
+ # Sets the window's padding (the number of pages on either side of the
385
+ # window page).
386
+ def padding=(padding)
387
+ @padding = padding < 0 ? 0 : padding
388
+ # Find the beginning and end pages of the window
389
+ @first = @paginator.has_page_number?(@page.number - @padding) ?
390
+ @paginator[@page.number - @padding] : @paginator.first
391
+ @last = @paginator.has_page_number?(@page.number + @padding) ?
392
+ @paginator[@page.number + @padding] : @paginator.last
393
+ end
394
+ attr_reader :padding, :first, :last
395
+
396
+ # Returns an array of Page objects in the current window.
397
+ def pages
398
+ (@first.number..@last.number).to_a.collect! {|n| @paginator[n]}
399
+ end
400
+ alias to_a :pages
401
+ end
402
+ end
403
+
404
+ end
405
+ end