will_paginate 3.0.pre4 → 3.0.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.

Files changed (51) hide show
  1. data/README.md +61 -0
  2. data/Rakefile +19 -36
  3. data/lib/will_paginate.rb +16 -14
  4. data/lib/will_paginate/{finders/active_record.rb → active_record.rb} +66 -35
  5. data/lib/will_paginate/array.rb +5 -5
  6. data/lib/will_paginate/collection.rb +12 -36
  7. data/lib/will_paginate/core_ext.rb +0 -28
  8. data/lib/will_paginate/data_mapper.rb +91 -0
  9. data/lib/will_paginate/i18n.rb +22 -0
  10. data/lib/will_paginate/locale/en.yml +33 -0
  11. data/lib/will_paginate/page_number.rb +57 -0
  12. data/lib/will_paginate/per_page.rb +27 -0
  13. data/lib/will_paginate/railtie.rb +13 -4
  14. data/lib/will_paginate/sequel.rb +36 -0
  15. data/lib/will_paginate/version.rb +1 -1
  16. data/lib/will_paginate/view_helpers.rb +136 -22
  17. data/lib/will_paginate/view_helpers/action_view.rb +129 -117
  18. data/lib/will_paginate/view_helpers/link_renderer.rb +10 -11
  19. data/lib/will_paginate/view_helpers/link_renderer_base.rb +2 -8
  20. data/lib/will_paginate/view_helpers/merb.rb +20 -7
  21. data/lib/will_paginate/view_helpers/sinatra.rb +41 -0
  22. data/spec/ci.rb +29 -0
  23. data/spec/collection_spec.rb +7 -23
  24. data/spec/console +9 -1
  25. data/spec/console_fixtures.rb +1 -3
  26. data/spec/database.yml +10 -10
  27. data/spec/finders/active_record_spec.rb +82 -28
  28. data/spec/finders/activerecord_test_connector.rb +9 -1
  29. data/spec/finders/data_mapper_spec.rb +59 -48
  30. data/spec/finders/data_mapper_test_connector.rb +8 -1
  31. data/spec/finders/sequel_spec.rb +9 -3
  32. data/spec/fixtures/project.rb +2 -0
  33. data/spec/page_number_spec.rb +65 -0
  34. data/spec/per_page_spec.rb +41 -0
  35. data/spec/spec_helper.rb +5 -29
  36. data/spec/view_helpers/action_view_spec.rb +48 -32
  37. data/spec/view_helpers/base_spec.rb +59 -7
  38. data/spec/view_helpers/link_renderer_base_spec.rb +7 -12
  39. data/spec/view_helpers/view_example_group.rb +1 -0
  40. metadata +22 -23
  41. data/CHANGELOG.rdoc +0 -105
  42. data/README.rdoc +0 -111
  43. data/lib/will_paginate/deprecation.rb +0 -50
  44. data/lib/will_paginate/finders.rb +0 -9
  45. data/lib/will_paginate/finders/active_resource.rb +0 -51
  46. data/lib/will_paginate/finders/base.rb +0 -112
  47. data/lib/will_paginate/finders/data_mapper.rb +0 -30
  48. data/lib/will_paginate/finders/sequel.rb +0 -23
  49. data/lib/will_paginate/view_helpers/base.rb +0 -126
  50. data/spec/finders/active_resource_spec.rb +0 -52
  51. data/spec/finders_spec.rb +0 -76
@@ -1,112 +0,0 @@
1
- require 'will_paginate/core_ext'
2
-
3
- module WillPaginate
4
- module Finders
5
- # = Database-agnostic finder module
6
- #
7
- # Out of the box, will_paginate supports hooking in several ORMs to
8
- # provide paginating finders based on their API. As of this writing, the
9
- # supported libraries are:
10
- #
11
- # * ActiveRecord
12
- # * DataMapper
13
- # * Sequel
14
- #
15
- # It's easy to write your own adapter for anything that can load data with
16
- # explicit limit and offset settings. DataMapper adapter is a nice and
17
- # compact example of writing an adapter to bring the +paginate+ method to
18
- # DataMapper models.
19
- #
20
- # == The importance of SQL's <tt>ORDER BY</tt>
21
- #
22
- # In most ORMs, <tt>:order</tt> parameter specifies columns for the
23
- # <tt>ORDER BY</tt> clause in SQL. It is important to have it, since
24
- # pagination only makes sense with ordered sets. Without the order clause,
25
- # databases aren't required to do consistent ordering when performing
26
- # <tt>SELECT</tt> queries.
27
- #
28
- # Ordering by a field for which many records share the same value (e.g.
29
- # "status") can still result in incorrect ordering with some databases (MS
30
- # SQL and Postgres for instance). With these databases it's recommend that
31
- # you order by primary key as well. That is, instead of ordering by
32
- # "status DESC", use the alternative "status DESC, id DESC" and this will
33
- # yield consistent results.
34
- #
35
- # Therefore, make sure you are doing ordering on a column that makes the
36
- # most sense in the current context. Make that obvious to the user, also.
37
- # For perfomance reasons you will also want to add an index to that column.
38
- module Base
39
- def per_page
40
- @per_page ||= 30
41
- end
42
-
43
- def per_page=(limit)
44
- @per_page = limit.to_i
45
- end
46
-
47
- # This is the main paginating finder.
48
- #
49
- # == Special parameters for paginating finders
50
- # * <tt>:page</tt> -- REQUIRED, but defaults to 1 if false or nil
51
- # * <tt>:per_page</tt> -- defaults to <tt>CurrentModel.per_page</tt> (which is 30 if not overridden)
52
- # * <tt>:total_entries</tt> -- use only if you manually count total entries
53
- # * <tt>:count</tt> -- additional options that are passed on to +count+
54
- # * <tt>:finder</tt> -- name of the finder method to use (default: "find")
55
- #
56
- # All other options (+conditions+, +order+, ...) are forwarded to +find+
57
- # and +count+ calls.
58
- def paginate(*args, &block)
59
- options = args.pop
60
- page, per_page, total_entries = wp_parse_options(options)
61
-
62
- WillPaginate::Collection.create(page, per_page, total_entries) do |pager|
63
- query_options = options.except :page, :per_page, :total_entries
64
- wp_query(query_options, pager, args, &block)
65
- end
66
- end
67
-
68
- # Iterates through all records by loading one page at a time. This is useful
69
- # for migrations or any other use case where you don't want to load all the
70
- # records in memory at once.
71
- #
72
- # It uses +paginate+ internally; therefore it accepts all of its options.
73
- # You can specify a starting page with <tt>:page</tt> (default is 1). Default
74
- # <tt>:order</tt> is <tt>"id"</tt>, override if necessary.
75
- #
76
- # {Jamis Buck describes this}[http://weblog.jamisbuck.org/2007/4/6/faking-cursors-in-activerecord]
77
- # and also uses a more efficient way for MySQL.
78
- def paginated_each(options = {}, &block)
79
- options = { :order => 'id', :page => 1 }.merge options
80
- options[:page] = options[:page].to_i
81
- options[:total_entries] = 0 # skip the individual count queries
82
- total = 0
83
-
84
- begin
85
- collection = paginate(options)
86
- total += collection.each(&block).size
87
- options[:page] += 1
88
- end until collection.size < collection.per_page
89
-
90
- total
91
- end
92
-
93
- protected
94
-
95
- def wp_parse_options(options) #:nodoc:
96
- raise ArgumentError, 'parameter hash expected' unless Hash === options
97
- raise ArgumentError, ':page parameter required' unless options.key? :page
98
-
99
- if options[:count] and options[:total_entries]
100
- raise ArgumentError, ':count and :total_entries are mutually exclusive'
101
- end
102
-
103
- page = options[:page] || 1
104
- per_page = options[:per_page] || self.per_page
105
- total = options[:total_entries]
106
-
107
- return [page, per_page, total]
108
- end
109
-
110
- end
111
- end
112
- end
@@ -1,30 +0,0 @@
1
- require 'will_paginate/finders/base'
2
- require 'dm-core'
3
-
4
- module WillPaginate::Finders
5
- module DataMapper
6
- include WillPaginate::Finders::Base
7
-
8
- protected
9
-
10
- def wp_query(options, pager, args, &block) #:nodoc
11
- find_options = options.except(:count).update(:offset => pager.offset, :limit => pager.per_page)
12
-
13
- pager.replace all(find_options, &block)
14
-
15
- unless pager.total_entries
16
- pager.total_entries = wp_count(options)
17
- end
18
- end
19
-
20
- def wp_count(options) #:nodoc
21
- count_options = options.except(:count, :order)
22
- # merge the hash found in :count
23
- count_options.update options[:count] if options[:count]
24
-
25
- count_options.empty?? count() : count(count_options)
26
- end
27
- end
28
- end
29
-
30
- DataMapper::Model.send(:include, WillPaginate::Finders::DataMapper)
@@ -1,23 +0,0 @@
1
- require 'will_paginate/core_ext'
2
- require 'sequel'
3
- require 'sequel/extensions/pagination'
4
-
5
- existing_methods = Sequel::Dataset::Pagination.instance_methods
6
-
7
- Sequel::Dataset::Pagination.module_eval do
8
- # it should quack like a WillPaginate::Collection
9
-
10
- alias :total_pages :page_count unless existing_methods.include_method? :total_pages
11
- alias :per_page :page_size unless existing_methods.include_method? :per_page
12
- alias :previous_page :prev_page unless existing_methods.include_method? :previous_page
13
- alias :total_entries :pagination_record_count unless existing_methods.include_method? :total_entries
14
-
15
- def out_of_bounds?
16
- current_page > total_pages
17
- end
18
-
19
- # Current offset of the paginated collection
20
- def offset
21
- (current_page - 1) * per_page
22
- end
23
- end
@@ -1,126 +0,0 @@
1
- require 'will_paginate/core_ext'
2
- require 'will_paginate/view_helpers'
3
-
4
- module WillPaginate
5
- module ViewHelpers
6
- # = The main view helpers module
7
- #
8
- # This is the base module which provides the +will_paginate+ view helper.
9
- module Base
10
- # Renders Digg/Flickr-style pagination for a WillPaginate::Collection object. Nil is
11
- # returned if there is only one page in total; pagination links aren't needed in that case.
12
- #
13
- # ==== Options
14
- # * <tt>:class</tt> -- CSS class name for the generated DIV (default: "pagination")
15
- # * <tt>:previous_label</tt> -- default: "« Previous"
16
- # * <tt>:next_label</tt> -- default: "Next »"
17
- # * <tt>:inner_window</tt> -- how many links are shown around the current page (default: 4)
18
- # * <tt>:outer_window</tt> -- how many links are around the first and the last page (default: 1)
19
- # * <tt>:separator</tt> -- string separator for page HTML elements (default: single space)
20
- # * <tt>:param_name</tt> -- parameter name for page number in URLs (default: <tt>:page</tt>)
21
- # * <tt>:params</tt> -- additional parameters when generating pagination links
22
- # (eg. <tt>:controller => "foo", :action => nil</tt>)
23
- # * <tt>:renderer</tt> -- class name, class or instance of a link renderer (default:
24
- # <tt>WillPaginate::LinkRenderer</tt>)
25
- # * <tt>:page_links</tt> -- when false, only previous/next links are rendered (default: true)
26
- # * <tt>:container</tt> -- toggles rendering of the DIV container for pagination links, set to
27
- # false only when you are rendering your own pagination markup (default: true)
28
- # * <tt>:id</tt> -- HTML ID for the container (default: nil). Pass +true+ to have the ID
29
- # automatically generated from the class name of objects in collection: for example, paginating
30
- # ArticleComment models would yield an ID of "article_comments_pagination".
31
- #
32
- # All options beside listed ones are passed as HTML attributes to the container
33
- # element for pagination links (the DIV). For example:
34
- #
35
- # <%= will_paginate @posts, :id => 'wp_posts' %>
36
- #
37
- # ... will result in:
38
- #
39
- # <div class="pagination" id="wp_posts"> ... </div>
40
- #
41
- def will_paginate(collection, options = {})
42
- # early exit if there is nothing to render
43
- return nil unless collection.total_pages > 1
44
-
45
- options = WillPaginate::ViewHelpers.pagination_options.merge(options)
46
-
47
- if options[:prev_label]
48
- WillPaginate::Deprecation::warn(":prev_label view parameter is now :previous_label; the old name has been deprecated.")
49
- options[:previous_label] = options.delete(:prev_label)
50
- end
51
-
52
- # get the renderer instance
53
- renderer = case options[:renderer]
54
- when String
55
- options[:renderer].constantize.new
56
- when Class
57
- options[:renderer].new
58
- else
59
- options[:renderer]
60
- end
61
- # render HTML for pagination
62
- renderer.prepare collection, options, self
63
- renderer.to_html
64
- end
65
-
66
- # Renders a helpful message with numbers of displayed vs. total entries.
67
- # You can use this as a blueprint for your own, similar helpers.
68
- #
69
- # <%= page_entries_info @posts %>
70
- # #-> Displaying posts 6 - 10 of 26 in total
71
- #
72
- # By default, the message will use the humanized class name of objects
73
- # in collection: for instance, "project types" for ProjectType models.
74
- # Override this to your liking with the <tt>:entry_name</tt> parameter:
75
- #
76
- # <%= page_entries_info @posts, :entry_name => 'item' %>
77
- # #-> Displaying items 6 - 10 of 26 in total
78
- #
79
- # Entry name is entered in singular and pluralized with
80
- # <tt>String#pluralize</tt> method from ActiveSupport. If it isn't
81
- # loaded, specify plural with <tt>:plural_name</tt> parameter:
82
- #
83
- # <%= page_entries_info @posts, :entry_name => 'item', :plural_name => 'items' %>
84
- #
85
- # By default, this method produces HTML output. You can trigger plain
86
- # text output by passing <tt>:html => false</tt> in options.
87
- def page_entries_info(collection, options = {})
88
- entry_name = options[:entry_name] || (collection.empty?? 'entry' :
89
- collection.first.class.name.underscore.gsub('_', ' '))
90
-
91
- plural_name = if options[:plural_name]
92
- options[:plural_name]
93
- elsif entry_name == 'entry'
94
- plural_name = 'entries'
95
- elsif entry_name.respond_to? :pluralize
96
- plural_name = entry_name.pluralize
97
- else
98
- entry_name + 's'
99
- end
100
-
101
- unless options[:html] == false
102
- b = '<b>'
103
- eb = '</b>'
104
- sp = '&nbsp;'
105
- else
106
- b = eb = ''
107
- sp = ' '
108
- end
109
-
110
- if collection.total_pages < 2
111
- case collection.size
112
- when 0; "No #{plural_name} found"
113
- when 1; "Displaying #{b}1#{eb} #{entry_name}"
114
- else; "Displaying #{b}all #{collection.size}#{eb} #{plural_name}"
115
- end
116
- else
117
- %{Displaying #{plural_name} #{b}%d#{sp}-#{sp}%d#{eb} of #{b}%d#{eb} in total} % [
118
- collection.offset + 1,
119
- collection.offset + collection.length,
120
- collection.total_entries
121
- ]
122
- end
123
- end
124
- end
125
- end
126
- end
@@ -1,52 +0,0 @@
1
- require 'spec_helper'
2
- require 'will_paginate/finders/active_resource'
3
- require 'active_resource/http_mock'
4
-
5
- class AresProject < ActiveResource::Base
6
- self.site = 'http://localhost:4000'
7
- end
8
-
9
- describe WillPaginate::Finders::ActiveResource do
10
-
11
- before :all do
12
- # ActiveResource::HttpMock.respond_to do |mock|
13
- # mock.get "/ares_projects.xml?page=1&per_page=5", {}, [].to_xml
14
- # end
15
- end
16
-
17
- it "should integrate with ActiveResource::Base" do
18
- ActiveResource::Base.should respond_to(:paginate)
19
- end
20
-
21
- it "should error when no parameters for #paginate" do
22
- lambda { AresProject.paginate }.should raise_error(ArgumentError)
23
- end
24
-
25
- it "should paginate" do
26
- AresProject.expects(:find_every).with(:params => { :page => 1, :per_page => 5 }).returns([])
27
- AresProject.paginate(:page => 1, :per_page => 5)
28
- end
29
-
30
- it "should have 30 per_page as default" do
31
- AresProject.expects(:find_every).with(:params => { :page => 1, :per_page => 30 }).returns([])
32
- AresProject.paginate(:page => 1)
33
- end
34
-
35
- it "should support #paginate(:all)" do
36
- lambda { AresProject.paginate(:all) }.should raise_error(ArgumentError)
37
- end
38
-
39
- it "should error #paginate(:other)" do
40
- lambda { AresProject.paginate(:first) }.should raise_error(ArgumentError)
41
- end
42
-
43
- protected
44
-
45
- def create(page = 2, limit = 5, total = nil, &block)
46
- if block_given?
47
- WillPaginate::Collection.create(page, limit, total, &block)
48
- else
49
- WillPaginate::Collection.new(page, limit, total)
50
- end
51
- end
52
- end
data/spec/finders_spec.rb DELETED
@@ -1,76 +0,0 @@
1
- require 'spec_helper'
2
- require 'will_paginate/finders/base'
3
-
4
- class Model
5
- extend WillPaginate::Finders::Base
6
- end
7
-
8
- describe WillPaginate::Finders::Base do
9
- it "should define default per_page of 30" do
10
- Model.per_page.should == 30
11
- end
12
-
13
- it "should allow to set custom per_page" do
14
- begin
15
- Model.per_page = 25
16
- Model.per_page.should == 25
17
- ensure
18
- Model.per_page = 30
19
- end
20
- end
21
-
22
- it "should result with WillPaginate::Collection" do
23
- Model.expects(:wp_query)
24
- Model.paginate(:page => nil).should be_instance_of(WillPaginate::Collection)
25
- end
26
-
27
- it "should delegate pagination to wp_query" do
28
- Model.expects(:wp_query).with({}, instance_of(WillPaginate::Collection), [])
29
- Model.paginate :page => nil
30
- end
31
-
32
- it "should complain when no hash parameters given" do
33
- lambda {
34
- Model.paginate
35
- }.should raise_error(ArgumentError, 'parameter hash expected')
36
- end
37
-
38
- it "should complain when no :page parameter present" do
39
- lambda {
40
- Model.paginate :per_page => 6
41
- }.should raise_error(ArgumentError, ':page parameter required')
42
- end
43
-
44
- it "should complain when both :count and :total_entries are given" do
45
- lambda {
46
- Model.paginate :page => 1, :count => {}, :total_entries => 1
47
- }.should raise_error(ArgumentError, ':count and :total_entries are mutually exclusive')
48
- end
49
-
50
- it "should never mangle options" do
51
- options = { :page => 1 }
52
- options.expects(:delete).never
53
- options_before = options.dup
54
-
55
- Model.expects(:wp_query)
56
- Model.paginate(options)
57
-
58
- options.should == options_before
59
- end
60
-
61
- it "should provide paginated_each functionality" do
62
- collection = stub('collection', :size => 5, :empty? => false, :per_page => 5)
63
- collection.expects(:each).times(2).returns(collection)
64
- last_collection = stub('collection', :size => 4, :empty? => false, :per_page => 5)
65
- last_collection.expects(:each).returns(last_collection)
66
-
67
- params = { :order => 'id', :total_entries => 0 }
68
-
69
- Model.expects(:paginate).with(params.merge(:page => 2)).returns(collection)
70
- Model.expects(:paginate).with(params.merge(:page => 3)).returns(collection)
71
- Model.expects(:paginate).with(params.merge(:page => 4)).returns(last_collection)
72
-
73
- total = Model.paginated_each(:page => '2') { }
74
- total.should == 14
75
- end
76
- end