will_paginate 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of will_paginate might be problematic. Click here for more details.
- data/CHANGELOG +3 -0
- data/LICENSE +18 -0
- data/Manifest.txt +34 -0
- data/README +152 -0
- data/Rakefile +65 -0
- data/config/release.rb +82 -0
- data/lib/will_paginate/collection.rb +132 -0
- data/lib/will_paginate/core_ext.rb +80 -0
- data/lib/will_paginate/finder.rb +214 -0
- data/lib/will_paginate/version.rb +9 -0
- data/lib/will_paginate/view_helpers.rb +218 -0
- data/lib/will_paginate.rb +63 -0
- data/setup.rb +1585 -0
- data/test/array_pagination_test.rb +131 -0
- data/test/boot.rb +23 -0
- data/test/console +9 -0
- data/test/finder_test.rb +322 -0
- data/test/fixtures/admin.rb +3 -0
- data/test/fixtures/developer.rb +11 -0
- data/test/fixtures/developers_projects.yml +13 -0
- data/test/fixtures/project.rb +15 -0
- data/test/fixtures/projects.yml +7 -0
- data/test/fixtures/replies.yml +29 -0
- data/test/fixtures/reply.rb +5 -0
- data/test/fixtures/schema.rb +38 -0
- data/test/fixtures/topic.rb +4 -0
- data/test/fixtures/topics.yml +30 -0
- data/test/fixtures/user.rb +2 -0
- data/test/fixtures/users.yml +35 -0
- data/test/helper.rb +25 -0
- data/test/lib/activerecord_test_case.rb +23 -0
- data/test/lib/activerecord_test_connector.rb +60 -0
- data/test/lib/load_fixtures.rb +13 -0
- data/test/pagination_test.rb +257 -0
- metadata +99 -0
data/CHANGELOG
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2008 PJ Hyett and Mislav Marohnić
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
5
|
+
the Software without restriction, including without limitation the rights to
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
7
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
8
|
+
subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
15
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
16
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest.txt
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
LICENSE
|
3
|
+
Manifest.txt
|
4
|
+
README
|
5
|
+
Rakefile
|
6
|
+
config/release.rb
|
7
|
+
lib/will_paginate.rb
|
8
|
+
lib/will_paginate/collection.rb
|
9
|
+
lib/will_paginate/core_ext.rb
|
10
|
+
lib/will_paginate/finder.rb
|
11
|
+
lib/will_paginate/version.rb
|
12
|
+
lib/will_paginate/view_helpers.rb
|
13
|
+
setup.rb
|
14
|
+
test/array_pagination_test.rb
|
15
|
+
test/boot.rb
|
16
|
+
test/console
|
17
|
+
test/finder_test.rb
|
18
|
+
test/fixtures/admin.rb
|
19
|
+
test/fixtures/developer.rb
|
20
|
+
test/fixtures/developers_projects.yml
|
21
|
+
test/fixtures/project.rb
|
22
|
+
test/fixtures/projects.yml
|
23
|
+
test/fixtures/replies.yml
|
24
|
+
test/fixtures/reply.rb
|
25
|
+
test/fixtures/schema.rb
|
26
|
+
test/fixtures/topic.rb
|
27
|
+
test/fixtures/topics.yml
|
28
|
+
test/fixtures/user.rb
|
29
|
+
test/fixtures/users.yml
|
30
|
+
test/helper.rb
|
31
|
+
test/lib/activerecord_test_case.rb
|
32
|
+
test/lib/activerecord_test_connector.rb
|
33
|
+
test/lib/load_fixtures.rb
|
34
|
+
test/pagination_test.rb
|
data/README
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
= WillPaginate
|
2
|
+
|
3
|
+
Pagination is just limiting the number of records displayed. Why should you let
|
4
|
+
it get in your way while developing, then? This plugin makes magic happen. Did
|
5
|
+
you ever want to be able to do just this on a model:
|
6
|
+
|
7
|
+
Post.paginate :page => 1, :order => 'created_at DESC'
|
8
|
+
|
9
|
+
... and then render the page links with a single view helper? Well, now you
|
10
|
+
can.
|
11
|
+
|
12
|
+
Ryan Bates made an awesome screencast[http://railscasts.com/episodes/51],
|
13
|
+
check it out.
|
14
|
+
|
15
|
+
Your mind reels with questions? Join our Google
|
16
|
+
group[http://groups.google.com/group/will_paginate].
|
17
|
+
|
18
|
+
You can find more documentation on the wiki[http://github.com/mislav/will_paginate/wikis].
|
19
|
+
|
20
|
+
== Example usage
|
21
|
+
|
22
|
+
Use a paginate finder in the controller:
|
23
|
+
|
24
|
+
@posts = Post.paginate_by_board_id @board.id, :page => params[:page], :order => 'updated_at DESC'
|
25
|
+
|
26
|
+
Yeah, +paginate+ works just like +find+ -- it just doesn't fetch all the
|
27
|
+
records. Don't forget to tell it which page you want, or it will complain!
|
28
|
+
Read more on WillPaginate::Finder::ClassMethods.
|
29
|
+
|
30
|
+
Render the posts in your view like you would normally do. When you need to render
|
31
|
+
pagination, just stick this in:
|
32
|
+
|
33
|
+
<%= will_paginate @posts %>
|
34
|
+
|
35
|
+
You're done. (Copy and paste the example fancy CSS styles from the bottom.) You
|
36
|
+
can find the option list at WillPaginate::ViewHelpers.
|
37
|
+
|
38
|
+
How does it know how much items to fetch per page? It asks your model by calling
|
39
|
+
its <tt>per_page</tt> class method. You can define it like this:
|
40
|
+
|
41
|
+
class Post < ActiveRecord::Base
|
42
|
+
cattr_reader :per_page
|
43
|
+
@@per_page = 50
|
44
|
+
end
|
45
|
+
|
46
|
+
... or like this:
|
47
|
+
|
48
|
+
class Post < ActiveRecord::Base
|
49
|
+
def self.per_page
|
50
|
+
50
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
... or don't worry about it at all. WillPaginate defines it to be <b>30</b> by default.
|
55
|
+
But you can always specify the count explicitly when calling +paginate+:
|
56
|
+
|
57
|
+
@posts = Post.paginate :page => params[:page], :per_page => 50
|
58
|
+
|
59
|
+
The +paginate+ finder wraps the original finder and returns your resultset that now has
|
60
|
+
some new properties. You can use the collection as you would with any ActiveRecord
|
61
|
+
resultset. WillPaginate view helpers also need that object to be able to render pagination:
|
62
|
+
|
63
|
+
<ol>
|
64
|
+
<% for post in @posts -%>
|
65
|
+
<li>Render `post` in some nice way.</li>
|
66
|
+
<% end -%>
|
67
|
+
</ol>
|
68
|
+
|
69
|
+
<p>Now let's render us some pagination!</p>
|
70
|
+
<%= will_paginate @posts %>
|
71
|
+
|
72
|
+
More detailed documentation:
|
73
|
+
|
74
|
+
* WillPaginate::Finder::ClassMethods for pagination on your models;
|
75
|
+
* WillPaginate::ViewHelpers for your views.
|
76
|
+
|
77
|
+
== Oh noes, a bug!
|
78
|
+
|
79
|
+
Tell us what happened so we can fix it, quick! Issues are filed on the Lighthouse project:
|
80
|
+
http://err.lighthouseapp.com/projects/466-plugins/tickets?q=tagged:will_paginate
|
81
|
+
|
82
|
+
Steps to make an awesome bug report:
|
83
|
+
|
84
|
+
1. Run <tt>rake test</tt> in the <i>will_paginate</i> directory. (You will need SQLite3.)
|
85
|
+
Copy the output if there are failing tests.
|
86
|
+
2. Register on Lighthouse to create a new ticket.
|
87
|
+
3. Write a descriptive, short title. Provide as much info as you can in the body.
|
88
|
+
Assign the ticket to Mislav and tag it with meaningful tags, <tt>"will_paginate"</tt>
|
89
|
+
being among them.
|
90
|
+
4. Yay! You will be notified on updates automatically.
|
91
|
+
|
92
|
+
Here is an example of a great bug report and patch:
|
93
|
+
http://err.lighthouseapp.com/projects/466/tickets/172-total_entries-ignored-in-paginate_by_sql
|
94
|
+
|
95
|
+
== Authors, credits, contact
|
96
|
+
|
97
|
+
Want to discuss, request features, ask questions? Join the Google group:
|
98
|
+
http://groups.google.com/group/will_paginate
|
99
|
+
|
100
|
+
Authors:: Mislav Marohnić, PJ Hyett
|
101
|
+
Original announcement:: http://errtheblog.com/post/929
|
102
|
+
Original PHP source:: http://www.strangerstudios.com/sandbox/pagination/diggstyle.php
|
103
|
+
|
104
|
+
All these people helped making will_paginate what it is now with their code
|
105
|
+
contributions or simply awesome ideas:
|
106
|
+
|
107
|
+
Chris Wanstrath, Dr. Nic Williams, K. Adam Christensen, Mike Garey, Bence
|
108
|
+
Golda, Matt Aimonetti, Charles Brian Quinn, Desi McAdam, James Coglan, Matijs
|
109
|
+
van Zuijlen, Maria, Brendan Ribera, Todd Willey, Bryan Helmkamp, Jan Berkel.
|
110
|
+
|
111
|
+
== Usable pagination in the UI
|
112
|
+
|
113
|
+
Copy the following CSS into your stylesheet for a good start:
|
114
|
+
|
115
|
+
.pagination {
|
116
|
+
padding: 3px;
|
117
|
+
margin: 3px;
|
118
|
+
}
|
119
|
+
.pagination a {
|
120
|
+
padding: 2px 5px 2px 5px;
|
121
|
+
margin: 2px;
|
122
|
+
border: 1px solid #aaaadd;
|
123
|
+
text-decoration: none;
|
124
|
+
color: #000099;
|
125
|
+
}
|
126
|
+
.pagination a:hover, .pagination a:active {
|
127
|
+
border: 1px solid #000099;
|
128
|
+
color: #000;
|
129
|
+
}
|
130
|
+
.pagination span.current {
|
131
|
+
padding: 2px 5px 2px 5px;
|
132
|
+
margin: 2px;
|
133
|
+
border: 1px solid #000099;
|
134
|
+
font-weight: bold;
|
135
|
+
background-color: #000099;
|
136
|
+
color: #FFF;
|
137
|
+
}
|
138
|
+
.pagination span.disabled {
|
139
|
+
padding: 2px 5px 2px 5px;
|
140
|
+
margin: 2px;
|
141
|
+
border: 1px solid #eee;
|
142
|
+
color: #ddd;
|
143
|
+
}
|
144
|
+
|
145
|
+
More reading about pagination as design pattern:
|
146
|
+
|
147
|
+
* Pagination 101:
|
148
|
+
http://kurafire.net/log/archive/2007/06/22/pagination-101
|
149
|
+
* Pagination gallery:
|
150
|
+
http://www.smashingmagazine.com/2007/11/16/pagination-gallery-examples-and-good-practices/
|
151
|
+
* Pagination on Yahoo Design Pattern Library:
|
152
|
+
http://developer.yahoo.com/ypatterns/parent.php?pattern=pagination
|
data/Rakefile
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require 'config/release'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the will_paginate plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.pattern = 'test/**/*_test.rb'
|
11
|
+
t.verbose = true
|
12
|
+
end
|
13
|
+
|
14
|
+
# I want to specify environment variables at call time
|
15
|
+
class EnvTestTask < Rake::TestTask
|
16
|
+
attr_accessor :env
|
17
|
+
|
18
|
+
def ruby(*args)
|
19
|
+
env.each { |key, value| ENV[key] = value } if env
|
20
|
+
super
|
21
|
+
env.keys.each { |key| ENV.delete key } if env
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
for configuration in %w( sqlite3 mysql postgres )
|
26
|
+
EnvTestTask.new("test_#{configuration}") do |t|
|
27
|
+
t.pattern = 'test/finder_test.rb'
|
28
|
+
t.verbose = true
|
29
|
+
t.env = { 'DB' => configuration }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
task :test_databases => %w(test_mysql test_sqlite3 test_postgres)
|
34
|
+
|
35
|
+
desc %{Test everything on SQLite3, MySQL and PostgreSQL}
|
36
|
+
task :test_full => %w(test test_mysql test_postgres)
|
37
|
+
|
38
|
+
desc %{Test everything with Rails 1.2.x and 2.0.x gems}
|
39
|
+
task :test_all do
|
40
|
+
all = Rake::Task['test_full']
|
41
|
+
ENV['RAILS_VERSION'] = '~>1.2.6'
|
42
|
+
all.invoke
|
43
|
+
# reset the invoked flag
|
44
|
+
%w( test_full test test_mysql test_postgres ).each do |name|
|
45
|
+
Rake::Task[name].instance_variable_set '@already_invoked', false
|
46
|
+
end
|
47
|
+
# do it again
|
48
|
+
ENV['RAILS_VERSION'] = '~>2.0.2'
|
49
|
+
all.invoke
|
50
|
+
end
|
51
|
+
|
52
|
+
desc 'Generate RDoc documentation for the will_paginate plugin.'
|
53
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
54
|
+
files = ['README', 'LICENSE', 'lib/**/*.rb']
|
55
|
+
rdoc.rdoc_files.add(files)
|
56
|
+
rdoc.main = "README" # page to start on
|
57
|
+
rdoc.title = "will_paginate"
|
58
|
+
|
59
|
+
templates = %w[/Users/chris/ruby/projects/err/rock/template.rb /var/www/rock/template.rb]
|
60
|
+
rdoc.template = templates.find { |t| File.exists? t }
|
61
|
+
|
62
|
+
rdoc.rdoc_dir = 'doc' # rdoc output folder
|
63
|
+
rdoc.options << '--inline-source'
|
64
|
+
rdoc.options << '--charset=UTF-8'
|
65
|
+
end
|
data/config/release.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'rubyforge'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
require 'lib/will_paginate/version.rb'
|
4
|
+
|
5
|
+
RUBYFORGE_NAME = 'will-paginate'
|
6
|
+
NAME = 'will_paginate'
|
7
|
+
version = WillPaginate::VERSION::STRING
|
8
|
+
|
9
|
+
DESCRIPTION = <<-DESC
|
10
|
+
A Rails plugin that provides pagination solutions
|
11
|
+
for querying models and rendering pagination links in views.
|
12
|
+
DESC
|
13
|
+
DESCRIPTION.strip!.gsub! /\s+/, ' '
|
14
|
+
|
15
|
+
changes = nil
|
16
|
+
|
17
|
+
spec = Gem::Specification.new do |s|
|
18
|
+
s.name = NAME
|
19
|
+
s.version = version
|
20
|
+
s.summary = s.description = DESCRIPTION
|
21
|
+
s.authors = ['Mislav Marohnić', 'PJ Hyett']
|
22
|
+
s.email = 'mislav.marohnic@gmail.com'
|
23
|
+
s.homepage = 'http://github.com/mislav/will_paginate/wikis'
|
24
|
+
s.rubyforge_project = RUBYFORGE_NAME
|
25
|
+
|
26
|
+
s.add_dependency 'activesupport', '>=1.4.4'
|
27
|
+
|
28
|
+
s.files = File.read("Manifest.txt").split("\n")
|
29
|
+
s.executables = s.files.grep(/^bin/) { |f| File.basename(f) }
|
30
|
+
|
31
|
+
s.bindir = "bin"
|
32
|
+
dirs = Dir['{lib,ext}']
|
33
|
+
s.require_paths = dirs unless dirs.empty?
|
34
|
+
|
35
|
+
s.rdoc_options = ['--main', 'README', '--inline-source', '--charset=UTF-8']
|
36
|
+
s.extra_rdoc_files = %w(README LICENSE) # + s.files.grep(/\.txt$/) - %w(Manifest.txt)
|
37
|
+
s.has_rdoc = true
|
38
|
+
end
|
39
|
+
|
40
|
+
Rake::GemPackageTask.new spec do |pkg|
|
41
|
+
pkg.need_tar = false
|
42
|
+
pkg.need_zip = false
|
43
|
+
end
|
44
|
+
|
45
|
+
desc 'Package and upload the release to rubyforge.'
|
46
|
+
task :release => [:clean, :package] do |t|
|
47
|
+
v = ENV["VERSION"] or abort "Must supply VERSION=x.y.z"
|
48
|
+
abort "Version doesn't match #{version}" if v != version
|
49
|
+
files = Dir["pkg/#{NAME}-#{version}.*"]
|
50
|
+
|
51
|
+
rf = RubyForge.new
|
52
|
+
puts "Logging in to RubyForge"
|
53
|
+
rf.login
|
54
|
+
|
55
|
+
c = rf.userconfig
|
56
|
+
c["release_notes"] = DESCRIPTION
|
57
|
+
c["release_changes"] = changes if changes
|
58
|
+
c["preformatted"] = true
|
59
|
+
|
60
|
+
puts "Releasing #{NAME} v. #{version}"
|
61
|
+
p files
|
62
|
+
rf.add_release RUBYFORGE_NAME, RUBYFORGE_NAME, version, *files
|
63
|
+
end
|
64
|
+
|
65
|
+
task :clean => [ :clobber_rdoc, :clobber_package ] do
|
66
|
+
removed = []
|
67
|
+
%w(diff diff.txt email.txt ri *.gem **/*~ **/.DS_Store).each do |pattern|
|
68
|
+
files = Dir[pattern]
|
69
|
+
next if files.empty?
|
70
|
+
FileUtils.rm_rf files
|
71
|
+
removed.concat files
|
72
|
+
end
|
73
|
+
puts "Removed files: #{removed.inspect}" unless removed.empty?
|
74
|
+
end
|
75
|
+
|
76
|
+
# desc 'Upload website files to rubyforge'
|
77
|
+
# task :website_upload do
|
78
|
+
# host = "#{rubyforge_username}@rubyforge.org"
|
79
|
+
# remote_dir = "/var/www/gforge-projects/#{PATH}/"
|
80
|
+
# local_dir = 'website'
|
81
|
+
# sh %{rsync -aCv #{local_dir}/ #{host}:#{remote_dir}}
|
82
|
+
# end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'will_paginate'
|
2
|
+
|
3
|
+
module WillPaginate
|
4
|
+
# = OMG, invalid page number!
|
5
|
+
# This is an ArgumentError raised in case a page was requested that is either
|
6
|
+
# zero or negative number. You should decide how do deal with such errors in
|
7
|
+
# the controller.
|
8
|
+
#
|
9
|
+
# This error is *not* raised when a page further than the last page is
|
10
|
+
# requested. Use <tt>WillPaginate::Collection#out_of_bounds?</tt> method to
|
11
|
+
# check for those cases and manually deal with them as you see fit.
|
12
|
+
class InvalidPage < ArgumentError
|
13
|
+
def initialize(page, page_num)
|
14
|
+
super "#{page.inspect} given as value, which translates to '#{page_num}' as page number"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Arrays returned from paginating finds are, in fact, instances of this.
|
19
|
+
# You may think of WillPaginate::Collection as an ordinary array with some
|
20
|
+
# extra properties. Those properties are used by view helpers to generate
|
21
|
+
# correct page links.
|
22
|
+
#
|
23
|
+
# WillPaginate::Collection also assists in rolling out your own pagination
|
24
|
+
# solutions: see +create+.
|
25
|
+
#
|
26
|
+
class Collection < Array
|
27
|
+
attr_reader :current_page, :per_page, :total_entries
|
28
|
+
|
29
|
+
# Arguments to this constructor are the current page number, per-page limit
|
30
|
+
# and the total number of entries. The last argument is optional because it
|
31
|
+
# is best to do lazy counting; in other words, count *conditionally* after
|
32
|
+
# populating the collection using the +replace+ method.
|
33
|
+
#
|
34
|
+
def initialize(page, per_page, total = nil)
|
35
|
+
@current_page = page.to_i
|
36
|
+
raise InvalidPage.new(page, @current_page) if @current_page < 1
|
37
|
+
@per_page = per_page.to_i
|
38
|
+
raise ArgumentError, "`per_page` setting cannot be less than 1 (#{@per_page} given)" if @per_page < 1
|
39
|
+
|
40
|
+
self.total_entries = total if total
|
41
|
+
end
|
42
|
+
|
43
|
+
# Just like +new+, but yields the object after instantiation and returns it
|
44
|
+
# afterwards. This is very useful for manual pagination:
|
45
|
+
#
|
46
|
+
# @entries = WillPaginate::Collection.create(1, 10) do |pager|
|
47
|
+
# result = Post.find(:all, :limit => pager.per_page, :offset => pager.offset)
|
48
|
+
# # inject the result array into the paginated collection:
|
49
|
+
# pager.replace(result)
|
50
|
+
#
|
51
|
+
# unless pager.total_entries
|
52
|
+
# # the pager didn't manage to guess the total count, do it manually
|
53
|
+
# pager.total_entries = Post.count
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# The possibilities with this are endless. For another example, here is how
|
58
|
+
# WillPaginate used to define pagination for Array instances:
|
59
|
+
#
|
60
|
+
# Array.class_eval do
|
61
|
+
# def paginate(page = 1, per_page = 15)
|
62
|
+
# WillPaginate::Collection.create(page, per_page, size) do |pager|
|
63
|
+
# pager.replace self[pager.offset, pager.per_page].to_a
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
def self.create(page, per_page, total = nil, &block)
|
69
|
+
pager = new(page, per_page, total)
|
70
|
+
yield pager
|
71
|
+
pager
|
72
|
+
end
|
73
|
+
|
74
|
+
# The total number of pages.
|
75
|
+
def page_count
|
76
|
+
@total_pages
|
77
|
+
end
|
78
|
+
|
79
|
+
# Helper method that is true when someone tries to fetch a page with a
|
80
|
+
# larger number than the last page. Can be used in combination with flashes
|
81
|
+
# and redirecting.
|
82
|
+
def out_of_bounds?
|
83
|
+
current_page > page_count
|
84
|
+
end
|
85
|
+
|
86
|
+
# Current offset of the paginated collection. If we're on the first page,
|
87
|
+
# it is always 0. If we're on the 2nd page and there are 30 entries per page,
|
88
|
+
# the offset is 30. This property is useful if you want to render ordinals
|
89
|
+
# besides your records: simply start with offset + 1.
|
90
|
+
#
|
91
|
+
def offset
|
92
|
+
(current_page - 1) * per_page
|
93
|
+
end
|
94
|
+
|
95
|
+
# current_page - 1 or nil if there is no previous page
|
96
|
+
def previous_page
|
97
|
+
current_page > 1 ? (current_page - 1) : nil
|
98
|
+
end
|
99
|
+
|
100
|
+
# current_page + 1 or nil if there is no next page
|
101
|
+
def next_page
|
102
|
+
current_page < page_count ? (current_page + 1) : nil
|
103
|
+
end
|
104
|
+
|
105
|
+
def total_entries=(number)
|
106
|
+
@total_entries = number.to_i
|
107
|
+
@total_pages = (@total_entries / per_page.to_f).ceil
|
108
|
+
end
|
109
|
+
|
110
|
+
# This is a magic wrapper for the original Array#replace method. It serves
|
111
|
+
# for populating the paginated collection after initialization.
|
112
|
+
#
|
113
|
+
# Why magic? Because it tries to guess the total number of entries judging
|
114
|
+
# by the size of given array. If it is shorter than +per_page+ limit, then we
|
115
|
+
# know we're on the last page. This trick is very useful for avoiding
|
116
|
+
# unnecessary hits to the database to do the counting after we fetched the
|
117
|
+
# data for the current page.
|
118
|
+
#
|
119
|
+
# However, after using +replace+ you should always test the value of
|
120
|
+
# +total_entries+ and set it to a proper value if it's +nil+. See the example
|
121
|
+
# in +create+.
|
122
|
+
def replace(array)
|
123
|
+
returning super do
|
124
|
+
# The collection is shorter then page limit? Rejoice, because
|
125
|
+
# then we know that we are on the last page!
|
126
|
+
if total_entries.nil? and length > 0 and length < per_page
|
127
|
+
self.total_entries = offset + length
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'will_paginate'
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
unless Hash.instance_methods.include? 'except'
|
5
|
+
Hash.class_eval do
|
6
|
+
# Returns a new hash without the given keys.
|
7
|
+
def except(*keys)
|
8
|
+
rejected = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
|
9
|
+
reject { |key,| rejected.include?(key) }
|
10
|
+
end
|
11
|
+
|
12
|
+
# Replaces the hash without only the given keys.
|
13
|
+
def except!(*keys)
|
14
|
+
replace(except(*keys))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
unless Hash.instance_methods.include? 'slice'
|
20
|
+
Hash.class_eval do
|
21
|
+
# Returns a new hash with only the given keys.
|
22
|
+
def slice(*keys)
|
23
|
+
allowed = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
|
24
|
+
reject { |key,| !allowed.include?(key) }
|
25
|
+
end
|
26
|
+
|
27
|
+
# Replaces the hash with only the given keys.
|
28
|
+
def slice!(*keys)
|
29
|
+
replace(slice(*keys))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
unless Hash.instance_methods.include? 'rec_merge!'
|
35
|
+
Hash.class_eval do
|
36
|
+
# Same as Hash#merge!, but recursively merges sub-hashes
|
37
|
+
# (stolen from Haml)
|
38
|
+
def rec_merge!(other)
|
39
|
+
other.each do |key, other_value|
|
40
|
+
value = self[key]
|
41
|
+
if value.is_a?(Hash) and other_value.is_a?(Hash)
|
42
|
+
value.rec_merge! other_value
|
43
|
+
else
|
44
|
+
self[key] = other_value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
self
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
require 'will_paginate/collection'
|
53
|
+
|
54
|
+
unless Array.instance_methods.include? 'paginate'
|
55
|
+
# http://www.desimcadam.com/archives/8
|
56
|
+
Array.class_eval do
|
57
|
+
def paginate(options_or_page = {}, per_page = nil)
|
58
|
+
if options_or_page.nil? or Fixnum === options_or_page
|
59
|
+
if defined? WillPaginate::Deprecation
|
60
|
+
WillPaginate::Deprecation.warn <<-DEPR
|
61
|
+
Array#paginate now conforms to the main, ActiveRecord::Base#paginate API. You should \
|
62
|
+
call it with a parameters hash (:page, :per_page). The old API (numbers as arguments) \
|
63
|
+
has been deprecated and is going to be unsupported in future versions of will_paginate.
|
64
|
+
DEPR
|
65
|
+
end
|
66
|
+
page = options_or_page
|
67
|
+
options = {}
|
68
|
+
else
|
69
|
+
options = options_or_page
|
70
|
+
page = options[:page]
|
71
|
+
raise ArgumentError, "wrong number of arguments (1 hash or 2 Fixnums expected)" if per_page
|
72
|
+
per_page = options[:per_page]
|
73
|
+
end
|
74
|
+
|
75
|
+
WillPaginate::Collection.create(page || 1, per_page || 30, options[:total_entries] || size) do |pager|
|
76
|
+
pager.replace self[pager.offset, pager.per_page].to_a
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|