will_paginate 2.3.16 → 3.0.pre

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.
Files changed (83) hide show
  1. data/CHANGELOG.rdoc +24 -80
  2. data/LICENSE +1 -1
  3. data/README.rdoc +125 -0
  4. data/Rakefile +26 -22
  5. data/lib/will_paginate/array.rb +25 -8
  6. data/lib/will_paginate/collection.rb +15 -28
  7. data/lib/will_paginate/core_ext.rb +26 -0
  8. data/lib/will_paginate/deprecation.rb +50 -0
  9. data/lib/will_paginate/finders/active_record.rb +158 -0
  10. data/lib/will_paginate/finders/active_resource.rb +51 -0
  11. data/lib/will_paginate/finders/base.rb +112 -0
  12. data/lib/will_paginate/finders/data_mapper.rb +30 -0
  13. data/lib/will_paginate/finders/sequel.rb +23 -0
  14. data/lib/will_paginate/finders.rb +9 -0
  15. data/lib/will_paginate/railtie.rb +26 -0
  16. data/lib/will_paginate/version.rb +5 -5
  17. data/lib/will_paginate/view_helpers/action_view.rb +142 -0
  18. data/lib/will_paginate/view_helpers/base.rb +126 -0
  19. data/lib/will_paginate/view_helpers/link_renderer.rb +130 -0
  20. data/lib/will_paginate/view_helpers/link_renderer_base.rb +83 -0
  21. data/lib/will_paginate/view_helpers/merb.rb +13 -0
  22. data/lib/will_paginate/view_helpers.rb +25 -436
  23. data/lib/will_paginate.rb +10 -84
  24. data/spec/collection_spec.rb +147 -0
  25. data/spec/console +8 -0
  26. data/spec/console_fixtures.rb +8 -0
  27. data/spec/database.yml +22 -0
  28. data/spec/finders/active_record_spec.rb +377 -0
  29. data/spec/finders/active_resource_spec.rb +52 -0
  30. data/spec/finders/activerecord_test_connector.rb +114 -0
  31. data/spec/finders/data_mapper_spec.rb +62 -0
  32. data/spec/finders/data_mapper_test_connector.rb +20 -0
  33. data/spec/finders/sequel_spec.rb +53 -0
  34. data/spec/finders/sequel_test_connector.rb +9 -0
  35. data/spec/finders_spec.rb +76 -0
  36. data/{test → spec}/fixtures/developer.rb +2 -3
  37. data/{test → spec}/fixtures/project.rb +2 -6
  38. data/{test → spec}/fixtures/projects.yml +1 -1
  39. data/{test → spec}/fixtures/reply.rb +1 -1
  40. data/spec/fixtures/topic.rb +7 -0
  41. data/spec/rcov.opts +2 -0
  42. data/spec/spec.opts +2 -0
  43. data/spec/spec_helper.rb +74 -0
  44. data/spec/tasks.rake +60 -0
  45. data/spec/view_helpers/action_view_spec.rb +345 -0
  46. data/spec/view_helpers/base_spec.rb +64 -0
  47. data/spec/view_helpers/link_renderer_base_spec.rb +84 -0
  48. data/spec/view_helpers/view_example_group.rb +103 -0
  49. metadata +60 -52
  50. data/README.md +0 -53
  51. data/lib/will_paginate/finder.rb +0 -264
  52. data/lib/will_paginate/i18n.rb +0 -29
  53. data/lib/will_paginate/locale/en.yml +0 -33
  54. data/lib/will_paginate/named_scope.rb +0 -170
  55. data/lib/will_paginate/named_scope_patch.rb +0 -37
  56. data/lib/will_paginate/per_page.rb +0 -27
  57. data/test/ci.rb +0 -56
  58. data/test/collection_test.rb +0 -160
  59. data/test/console +0 -8
  60. data/test/database.yml +0 -16
  61. data/test/finder_test.rb +0 -520
  62. data/test/fixtures/topic.rb +0 -12
  63. data/test/gemfiles/Gemfile.1.2 +0 -13
  64. data/test/gemfiles/Gemfile.1.2.lock +0 -39
  65. data/test/gemfiles/Gemfile.2.0 +0 -16
  66. data/test/gemfiles/Gemfile.2.0.lock +0 -28
  67. data/test/gemfiles/Gemfile.2.1 +0 -16
  68. data/test/gemfiles/Gemfile.2.1.lock +0 -28
  69. data/test/gemfiles/Gemfile.2.2 +0 -16
  70. data/test/gemfiles/Gemfile.2.2.lock +0 -28
  71. data/test/helper.rb +0 -34
  72. data/test/lib/activerecord_test_case.rb +0 -38
  73. data/test/lib/activerecord_test_connector.rb +0 -86
  74. data/test/lib/load_fixtures.rb +0 -12
  75. data/test/lib/view_test_process.rb +0 -186
  76. data/test/view_test.rb +0 -373
  77. /data/{test → spec}/fixtures/admin.rb +0 -0
  78. /data/{test → spec}/fixtures/developers_projects.yml +0 -0
  79. /data/{test → spec}/fixtures/replies.yml +0 -0
  80. /data/{test → spec}/fixtures/schema.rb +0 -0
  81. /data/{test → spec}/fixtures/topics.yml +0 -0
  82. /data/{test → spec}/fixtures/user.rb +0 -0
  83. /data/{test → spec}/fixtures/users.yml +0 -0
@@ -1,170 +0,0 @@
1
- module WillPaginate
2
- # This is a feature backported from Rails 2.1 because of its usefullness not only with will_paginate,
3
- # but in other aspects when managing complex conditions that you want to be reusable.
4
- module NamedScope
5
- # All subclasses of ActiveRecord::Base have two named_scopes:
6
- # * <tt>all</tt>, which is similar to a <tt>find(:all)</tt> query, and
7
- # * <tt>scoped</tt>, which allows for the creation of anonymous scopes, on the fly: <tt>Shirt.scoped(:conditions => {:color => 'red'}).scoped(:include => :washing_instructions)</tt>
8
- #
9
- # These anonymous scopes tend to be useful when procedurally generating complex queries, where passing
10
- # intermediate values (scopes) around as first-class objects is convenient.
11
- def self.included(base)
12
- base.class_eval do
13
- extend ClassMethods
14
- named_scope :scoped, lambda { |scope| scope }
15
- end
16
- end
17
-
18
- module ClassMethods
19
- def scopes
20
- read_inheritable_attribute(:scopes) || write_inheritable_attribute(:scopes, {})
21
- end
22
-
23
- # Adds a class method for retrieving and querying objects. A scope represents a narrowing of a database query,
24
- # such as <tt>:conditions => {:color => :red}, :select => 'shirts.*', :include => :washing_instructions</tt>.
25
- #
26
- # class Shirt < ActiveRecord::Base
27
- # named_scope :red, :conditions => {:color => 'red'}
28
- # named_scope :dry_clean_only, :joins => :washing_instructions, :conditions => ['washing_instructions.dry_clean_only = ?', true]
29
- # end
30
- #
31
- # The above calls to <tt>named_scope</tt> define class methods <tt>Shirt.red</tt> and <tt>Shirt.dry_clean_only</tt>. <tt>Shirt.red</tt>,
32
- # in effect, represents the query <tt>Shirt.find(:all, :conditions => {:color => 'red'})</tt>.
33
- #
34
- # Unlike Shirt.find(...), however, the object returned by <tt>Shirt.red</tt> is not an Array; it resembles the association object
35
- # constructed by a <tt>has_many</tt> declaration. For instance, you can invoke <tt>Shirt.red.find(:first)</tt>, <tt>Shirt.red.count</tt>,
36
- # <tt>Shirt.red.find(:all, :conditions => {:size => 'small'})</tt>. Also, just
37
- # as with the association objects, name scopes acts like an Array, implementing Enumerable; <tt>Shirt.red.each(&block)</tt>,
38
- # <tt>Shirt.red.first</tt>, and <tt>Shirt.red.inject(memo, &block)</tt> all behave as if Shirt.red really were an Array.
39
- #
40
- # These named scopes are composable. For instance, <tt>Shirt.red.dry_clean_only</tt> will produce all shirts that are both red and dry clean only.
41
- # Nested finds and calculations also work with these compositions: <tt>Shirt.red.dry_clean_only.count</tt> returns the number of garments
42
- # for which these criteria obtain. Similarly with <tt>Shirt.red.dry_clean_only.average(:thread_count)</tt>.
43
- #
44
- # All scopes are available as class methods on the ActiveRecord::Base descendent upon which the scopes were defined. But they are also available to
45
- # <tt>has_many</tt> associations. If,
46
- #
47
- # class Person < ActiveRecord::Base
48
- # has_many :shirts
49
- # end
50
- #
51
- # then <tt>elton.shirts.red.dry_clean_only</tt> will return all of Elton's red, dry clean
52
- # only shirts.
53
- #
54
- # Named scopes can also be procedural.
55
- #
56
- # class Shirt < ActiveRecord::Base
57
- # named_scope :colored, lambda { |color|
58
- # { :conditions => { :color => color } }
59
- # }
60
- # end
61
- #
62
- # In this example, <tt>Shirt.colored('puce')</tt> finds all puce shirts.
63
- #
64
- # Named scopes can also have extensions, just as with <tt>has_many</tt> declarations:
65
- #
66
- # class Shirt < ActiveRecord::Base
67
- # named_scope :red, :conditions => {:color => 'red'} do
68
- # def dom_id
69
- # 'red_shirts'
70
- # end
71
- # end
72
- # end
73
- #
74
- #
75
- # For testing complex named scopes, you can examine the scoping options using the
76
- # <tt>proxy_options</tt> method on the proxy itself.
77
- #
78
- # class Shirt < ActiveRecord::Base
79
- # named_scope :colored, lambda { |color|
80
- # { :conditions => { :color => color } }
81
- # }
82
- # end
83
- #
84
- # expected_options = { :conditions => { :colored => 'red' } }
85
- # assert_equal expected_options, Shirt.colored('red').proxy_options
86
- def named_scope(name, options = {})
87
- name = name.to_sym
88
- scopes[name] = lambda do |parent_scope, *args|
89
- Scope.new(parent_scope, case options
90
- when Hash
91
- options
92
- when Proc
93
- options.call(*args)
94
- end) { |*a| yield(*a) if block_given? }
95
- end
96
- (class << self; self end).instance_eval do
97
- define_method name do |*args|
98
- scopes[name].call(self, *args)
99
- end
100
- end
101
- end
102
- end
103
-
104
- class Scope
105
- attr_reader :proxy_scope, :proxy_options
106
-
107
- [].methods.each do |m|
108
- unless m =~ /(^__|^nil\?|^send|^object_id$|class|extend|^find$|count|sum|average|maximum|minimum|paginate|first|last|empty\?|respond_to\?)/
109
- delegate m, :to => :proxy_found
110
- end
111
- end
112
-
113
- delegate :scopes, :with_scope, :to => :proxy_scope
114
-
115
- def initialize(proxy_scope, options)
116
- [options[:extend]].flatten.each { |extension| extend extension } if options[:extend]
117
- extend Module.new { |*args| yield(*args) } if block_given?
118
- @proxy_scope, @proxy_options = proxy_scope, options.except(:extend)
119
- end
120
-
121
- def reload
122
- load_found; self
123
- end
124
-
125
- def first(*args)
126
- if args.first.kind_of?(Integer) || (@found && !args.first.kind_of?(Hash))
127
- proxy_found.first(*args)
128
- else
129
- find(:first, *args)
130
- end
131
- end
132
-
133
- def last(*args)
134
- if args.first.kind_of?(Integer) || (@found && !args.first.kind_of?(Hash))
135
- proxy_found.last(*args)
136
- else
137
- find(:last, *args)
138
- end
139
- end
140
-
141
- def empty?
142
- @found ? @found.empty? : count.zero?
143
- end
144
-
145
- def respond_to?(method, include_private = false)
146
- super || @proxy_scope.respond_to?(method, include_private)
147
- end
148
-
149
- protected
150
- def proxy_found
151
- @found || load_found
152
- end
153
-
154
- private
155
- def method_missing(method, *args)
156
- if scopes.include?(method)
157
- scopes[method].call(self, *args)
158
- else
159
- with_scope :find => proxy_options do
160
- proxy_scope.send(method, *args) { |*a| yield(*a) if block_given? }
161
- end
162
- end
163
- end
164
-
165
- def load_found
166
- @found = find(:all)
167
- end
168
- end
169
- end
170
- end
@@ -1,37 +0,0 @@
1
- ActiveRecord::Associations::AssociationProxy.class_eval do
2
- protected
3
- def with_scope(*args)
4
- @reflection.klass.send(:with_scope, *args) { |*a| yield(*a) if block_given? }
5
- end
6
- end
7
-
8
- [ ActiveRecord::Associations::AssociationCollection,
9
- ActiveRecord::Associations::HasManyThroughAssociation ].each do |klass|
10
- klass.class_eval do
11
- protected
12
- alias :method_missing_without_scopes :method_missing_without_paginate
13
- def method_missing_without_paginate(method, *args)
14
- if @reflection.klass.scopes.include?(method)
15
- @reflection.klass.scopes[method].call(self, *args) { |*a| yield(*a) if block_given? }
16
- else
17
- method_missing_without_scopes(method, *args) { |*a| yield(*a) if block_given? }
18
- end
19
- end
20
- end
21
- end
22
-
23
- # Rails 1.2.6
24
- ActiveRecord::Associations::HasAndBelongsToManyAssociation.class_eval do
25
- protected
26
- def method_missing(method, *args)
27
- if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method))
28
- super
29
- elsif @reflection.klass.scopes.include?(method)
30
- @reflection.klass.scopes[method].call(self, *args)
31
- else
32
- @reflection.klass.with_scope(:find => { :conditions => @finder_sql, :joins => @join_sql, :readonly => false }) do
33
- @reflection.klass.send(method, *args) { |*a| yield(*a) if block_given? }
34
- end
35
- end
36
- end
37
- end if ActiveRecord::Base.respond_to? :find_first
@@ -1,27 +0,0 @@
1
- module WillPaginate
2
- module PerPage
3
- def per_page
4
- defined?(@per_page) ? @per_page : WillPaginate.per_page
5
- end
6
-
7
- def per_page=(limit)
8
- @per_page = limit.to_i
9
- end
10
-
11
- def self.extended(base)
12
- base.extend Inheritance if base.is_a? Class
13
- end
14
-
15
- module Inheritance
16
- def inherited(subclass)
17
- super
18
- subclass.per_page = self.per_page
19
- end
20
- end
21
- end
22
-
23
- extend PerPage
24
-
25
- # default number of items per page
26
- self.per_page = 30
27
- end
data/test/ci.rb DELETED
@@ -1,56 +0,0 @@
1
- #!/usr/bin/env ruby
2
- databases = %w[ sqlite3 mysql postgres ]
3
- # skip mysql on 1.8.6 (doesn't work for unknown reason)
4
- run_mysql = !(ENV['TRAVIS'] && RUBY_VERSION == '1.8.6')
5
-
6
- def announce(name, msg)
7
- puts "\n\e[1;33m[#{name}] #{msg}\e[m\n"
8
- end
9
-
10
- def rails_version(gemfile)
11
- gemfile =~ /\d[\d.]*$/ ? $& : '2.3'
12
- end
13
-
14
- def system(*args)
15
- puts "$ #{args.join(' ')}"
16
- super
17
- end
18
-
19
- if ENV['TRAVIS']
20
- if run_mysql
21
- system "mysql -e 'create database will_paginate;' >/dev/null"
22
- abort "failed to create mysql database" unless $?.success?
23
- end
24
- system "psql -c 'create database will_paginate;' -U postgres >/dev/null"
25
- abort "failed to create postgres database" unless $?.success?
26
- end
27
-
28
- gemfiles = ['Gemfile']
29
- gemfiles.concat Dir['test/gemfiles/*'].reject { |f| f.include? '.lock' }.sort.reverse
30
-
31
- ruby19 = RUBY_VERSION > '1.9'
32
- ruby19_gemfiles = gemfiles.first
33
-
34
- bundler_options = ENV['TRAVIS'] ? "--path #{Dir.pwd}/vendor/bundle" : ''
35
-
36
- failed = false
37
-
38
- gemfiles.each do |gemfile|
39
- next if ruby19 and !ruby19_gemfiles.include? gemfile
40
- version = rails_version(gemfile)
41
- ENV['BUNDLE_GEMFILE'] = gemfile
42
- skip_install = gemfile == gemfiles.first
43
- if skip_install or system %(bundle install #{bundler_options})
44
- for db in databases
45
- next if 'mysql' == db and !run_mysql
46
- announce "Rails #{version}", "with #{db}"
47
- ENV['DB'] = db
48
- failed = true unless system %(bundle exec rake)
49
- end
50
- else
51
- # bundle install failed
52
- failed = true
53
- end
54
- end
55
-
56
- exit 1 if failed
@@ -1,160 +0,0 @@
1
- require 'helper'
2
- require 'will_paginate/array'
3
-
4
- class ArrayPaginationTest < Test::Unit::TestCase
5
-
6
- def setup ; end
7
-
8
- def test_simple
9
- collection = ('a'..'e').to_a
10
-
11
- [{ :page => 1, :per_page => 3, :expected => %w( a b c ) },
12
- { :page => 2, :per_page => 3, :expected => %w( d e ) },
13
- { :page => 1, :per_page => 5, :expected => %w( a b c d e ) },
14
- { :page => 3, :per_page => 5, :expected => [] },
15
- ].
16
- each do |conditions|
17
- expected = conditions.delete :expected
18
- assert_equal expected, collection.paginate(conditions)
19
- end
20
- end
21
-
22
- def test_defaults
23
- result = (1..50).to_a.paginate
24
- assert_equal 1, result.current_page
25
- assert_equal 30, result.size
26
- end
27
-
28
- def test_deprecated_api
29
- assert_raise(ArgumentError) { [].paginate(2) }
30
- assert_raise(ArgumentError) { [].paginate(2, 10) }
31
- end
32
-
33
- def test_total_entries_has_precedence
34
- result = %w(a b c).paginate :total_entries => 5
35
- assert_equal 5, result.total_entries
36
- end
37
-
38
- def test_argument_error_with_params_and_another_argument
39
- assert_raise ArgumentError do
40
- [].paginate({}, 5)
41
- end
42
- end
43
-
44
- def test_paginated_collection
45
- entries = %w(a b c)
46
- collection = create(2, 3, 10) do |pager|
47
- assert_equal entries, pager.replace(entries)
48
- end
49
-
50
- assert_equal entries, collection
51
- assert_respond_to_all collection, %w(total_pages each offset size current_page per_page total_entries)
52
- assert_kind_of Array, collection
53
- assert_instance_of Array, collection.entries
54
- assert_equal 3, collection.offset
55
- assert_equal 4, collection.total_pages
56
- assert !collection.out_of_bounds?
57
- end
58
-
59
- def test_previous_next_pages
60
- collection = create(1, 1, 3)
61
- assert_nil collection.previous_page
62
- assert_equal 2, collection.next_page
63
-
64
- collection = create(2, 1, 3)
65
- assert_equal 1, collection.previous_page
66
- assert_equal 3, collection.next_page
67
-
68
- collection = create(3, 1, 3)
69
- assert_equal 2, collection.previous_page
70
- assert_nil collection.next_page
71
- end
72
-
73
- def test_out_of_bounds
74
- entries = create(2, 3, 2){}
75
- assert entries.out_of_bounds?
76
-
77
- entries = create(1, 3, 2){}
78
- assert !entries.out_of_bounds?
79
- end
80
-
81
- def test_guessing_total_count
82
- entries = create do |pager|
83
- # collection is shorter than limit
84
- pager.replace array
85
- end
86
- assert_equal 8, entries.total_entries
87
-
88
- entries = create(2, 5, 10) do |pager|
89
- # collection is shorter than limit, but we have an explicit count
90
- pager.replace array
91
- end
92
- assert_equal 10, entries.total_entries
93
-
94
- entries = create do |pager|
95
- # collection is the same as limit; we can't guess
96
- pager.replace array(5)
97
- end
98
- assert_equal nil, entries.total_entries
99
-
100
- entries = create do |pager|
101
- # collection is empty; we can't guess
102
- pager.replace array(0)
103
- end
104
- assert_equal nil, entries.total_entries
105
-
106
- entries = create(1) do |pager|
107
- # collection is empty and we're on page 1,
108
- # so the whole thing must be empty, too
109
- pager.replace array(0)
110
- end
111
- assert_equal 0, entries.total_entries
112
- end
113
-
114
- def test_invalid_page
115
- bad_inputs = [0, -1, nil, '', 'Schnitzel']
116
-
117
- bad_inputs.each do |bad|
118
- assert_raise(WillPaginate::InvalidPage) { create bad }
119
- end
120
- end
121
-
122
- def test_invalid_offset
123
- error = assert_raise(WillPaginate::InvalidPage) { create(307445734561825862, 30) }
124
- assert_equal "invalid offset: 9223372036854775830", error.message
125
- end
126
-
127
- def test_page_count_was_removed
128
- assert_raise(NoMethodError) { create.page_count }
129
- # It's `total_pages` now.
130
- end
131
-
132
- def test_inherits_global_per_page
133
- col = WillPaginate::Collection.new(1)
134
- assert_equal 30, col.per_page
135
-
136
- WillPaginate.per_page = 12
137
- begin
138
- col = WillPaginate::Collection.new(1)
139
- assert_equal 12, col.per_page
140
-
141
- col = ('a'..'z').to_a.paginate(:page => 1)
142
- assert_equal 12, col.per_page
143
- ensure
144
- WillPaginate.per_page = 30
145
- end
146
- end
147
-
148
- private
149
- def create(page = 2, limit = 5, total = nil, &block)
150
- if block_given?
151
- WillPaginate::Collection.create(page, limit, total, &block)
152
- else
153
- WillPaginate::Collection.new(page, limit, total)
154
- end
155
- end
156
-
157
- def array(size = 3)
158
- Array.new(size)
159
- end
160
- end
data/test/console DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env ruby
2
- irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
3
-
4
- opts = %w[ --simple-prompt ]
5
- opts << '-rirb/completion'
6
- opts << '-rlib/load_fixtures'
7
-
8
- exec irb, '-Ilib:test', *opts
data/test/database.yml DELETED
@@ -1,16 +0,0 @@
1
- sqlite3:
2
- database: ":memory:"
3
- adapter: sqlite3
4
- timeout: 500
5
-
6
- mysql:
7
- adapter: mysql
8
- database: will_paginate
9
- username:
10
- encoding: utf8
11
-
12
- postgres:
13
- adapter: postgresql
14
- database: will_paginate
15
- username: postgres
16
- min_messages: warning