will_paginate 3.0.pre2 → 3.0.pre4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of will_paginate might be problematic. Click here for more details.
- data/README.rdoc +2 -16
- data/Rakefile +13 -3
- data/lib/will_paginate/core_ext.rb +5 -16
- data/lib/will_paginate/finders/active_record.rb +130 -121
- data/lib/will_paginate/railtie.rb +9 -11
- data/lib/will_paginate/version.rb +1 -1
- data/lib/will_paginate/view_helpers/action_view.rb +8 -6
- data/lib/will_paginate/view_helpers/link_renderer.rb +6 -4
- data/spec/console +2 -6
- data/spec/console_fixtures.rb +24 -2
- data/spec/finders/active_record_spec.rb +107 -30
- data/spec/finders/activerecord_test_connector.rb +24 -33
- data/spec/finders/data_mapper_spec.rb +10 -4
- data/spec/finders/data_mapper_test_connector.rb +2 -0
- data/spec/finders/sequel_spec.rb +11 -3
- data/spec/fixtures/replies.yml +5 -5
- data/spec/fixtures/reply.rb +4 -2
- data/spec/fixtures/topics.yml +4 -4
- data/spec/spec_helper.rb +3 -4
- data/spec/view_helpers/action_view_spec.rb +13 -1
- data/spec/view_helpers/view_example_group.rb +17 -7
- metadata +4 -22
- data/spec/rcov.opts +0 -2
- data/spec/spec.opts +0 -2
- data/spec/tasks.rake +0 -60
data/README.rdoc
CHANGED
@@ -31,23 +31,9 @@ them mixed in.
|
|
31
31
|
|
32
32
|
== Installation
|
33
33
|
|
34
|
-
|
34
|
+
In your Gemfile (if using Bundler):
|
35
35
|
|
36
|
-
gem
|
37
|
-
|
38
|
-
In <b>Rails 2.1</b>, add a gem dependency:
|
39
|
-
|
40
|
-
# for Rails 2.1 and newer
|
41
|
-
config.gem 'mislav-will_paginate', :lib => 'will_paginate', :version => '~> 3.0'
|
42
|
-
|
43
|
-
If you're using Rails 2.0 or older, or any other Ruby framework, just add a simple require to a file
|
44
|
-
that initializes your application. For example, in Rails you would put this at the end of
|
45
|
-
"config/environment.rb".
|
46
|
-
|
47
|
-
gem 'mislav-will_paginate', '~> 3.0'
|
48
|
-
require 'will_paginate'
|
49
|
-
|
50
|
-
That's it. Remember to install the gem on <strong>all</strong> machines that you are deploying to.
|
36
|
+
gem 'will_paginate', '~> 3.0.beta'
|
51
37
|
|
52
38
|
<i>There are extensive {installation
|
53
39
|
instructions}[http://github.com/mislav/will_paginate/wikis/installation] on {the
|
data/Rakefile
CHANGED
@@ -1,10 +1,20 @@
|
|
1
1
|
require 'rake/rdoctask'
|
2
|
+
require 'rspec/core/rake_task'
|
2
3
|
|
3
|
-
load 'spec/tasks.rake'
|
4
|
-
|
5
|
-
desc 'Default: run specs.'
|
6
4
|
task :default => :spec
|
7
5
|
|
6
|
+
desc 'Run ALL OF the specs'
|
7
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
8
|
+
# t.ruby_opts = '-w'
|
9
|
+
end
|
10
|
+
|
11
|
+
namespace :spec do
|
12
|
+
desc "Run Rails specs"
|
13
|
+
RSpec::Core::RakeTask.new(:rails) do |t|
|
14
|
+
t.pattern = %w'spec/finders/active_record_spec.rb spec/view_helpers/action_view_spec.rb'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
8
18
|
desc 'Generate RDoc documentation for the will_paginate plugin.'
|
9
19
|
Rake::RDocTask.new(:rdoc) do |rdoc|
|
10
20
|
rdoc.rdoc_files.include('README.rdoc', 'LICENSE', 'CHANGELOG.rdoc').
|
@@ -1,20 +1,9 @@
|
|
1
1
|
require 'set'
|
2
2
|
require 'will_paginate/array'
|
3
3
|
|
4
|
-
#
|
5
|
-
# because `methods`, `instance_methods` and others return strings in 1.8 and symbols in 1.9
|
6
|
-
#
|
7
|
-
# ['foo', 'bar'].include_method?(:foo) # => true
|
8
|
-
class Array
|
9
|
-
def include_method?(name)
|
10
|
-
name = name.to_sym
|
11
|
-
!!(find { |item| item.to_sym == name })
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
## everything below copied from ActiveSupport so we don't depend on it ##
|
4
|
+
# copied from ActiveSupport so we don't depend on it
|
16
5
|
|
17
|
-
unless Hash.
|
6
|
+
unless Hash.method_defined? :except
|
18
7
|
Hash.class_eval do
|
19
8
|
# Returns a new hash without the given keys.
|
20
9
|
def except(*keys)
|
@@ -29,7 +18,7 @@ unless Hash.instance_methods.include_method? :except
|
|
29
18
|
end
|
30
19
|
end
|
31
20
|
|
32
|
-
unless Hash.
|
21
|
+
unless Hash.method_defined? :slice
|
33
22
|
Hash.class_eval do
|
34
23
|
# Returns a new hash with only the given keys.
|
35
24
|
def slice(*keys)
|
@@ -44,7 +33,7 @@ unless Hash.instance_methods.include_method? :slice
|
|
44
33
|
end
|
45
34
|
end
|
46
35
|
|
47
|
-
unless String.
|
36
|
+
unless String.method_defined? :constantize
|
48
37
|
String.class_eval do
|
49
38
|
def constantize
|
50
39
|
unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ self
|
@@ -56,7 +45,7 @@ unless String.instance_methods.include_method? :constantize
|
|
56
45
|
end
|
57
46
|
end
|
58
47
|
|
59
|
-
unless String.
|
48
|
+
unless String.method_defined? :underscore
|
60
49
|
String.class_eval do
|
61
50
|
def underscore
|
62
51
|
self.to_s.gsub(/::/, '/').
|
@@ -5,154 +5,163 @@ module WillPaginate::Finders
|
|
5
5
|
# = Paginating finders for ActiveRecord models
|
6
6
|
#
|
7
7
|
# WillPaginate adds +paginate+, +per_page+ and other methods to
|
8
|
-
# ActiveRecord::Base class methods and associations.
|
9
|
-
# +method_missing+ to intercept pagination calls to dynamic finders such as
|
10
|
-
# +paginate_by_user_id+ and translate them to ordinary finders
|
11
|
-
# (+find_all_by_user_id+ in this case).
|
8
|
+
# ActiveRecord::Base class methods and associations.
|
12
9
|
#
|
13
10
|
# In short, paginating finders are equivalent to ActiveRecord finders; the
|
14
11
|
# only difference is that we start with "paginate" instead of "find" and
|
15
12
|
# that <tt>:page</tt> is required parameter:
|
16
13
|
#
|
17
14
|
# @posts = Post.paginate :all, :page => params[:page], :order => 'created_at DESC'
|
18
|
-
#
|
19
|
-
# In paginating finders, "all" is implicit. There is no sense in paginating
|
20
|
-
# a single record, right? So, you can drop the <tt>:all</tt> argument:
|
21
|
-
#
|
22
|
-
# Post.paginate(...) => Post.find :all
|
23
|
-
# Post.paginate_all_by_something => Post.find_all_by_something
|
24
|
-
# Post.paginate_by_something => Post.find_all_by_something
|
25
15
|
#
|
26
16
|
module ActiveRecord
|
27
|
-
include WillPaginate::Finders::Base
|
28
|
-
|
29
17
|
# In Rails, this is automatically called to mix-in pagination functionality to ActiveRecord.
|
30
18
|
def self.enable!
|
31
|
-
::ActiveRecord::Base.
|
32
|
-
|
19
|
+
::ActiveRecord::Base.extend Base
|
20
|
+
::ActiveRecord::Base.extend ActiveRecord::Pagination
|
21
|
+
::ActiveRecord::Base.extend ActiveRecord::BaseMethods
|
22
|
+
|
23
|
+
klasses = [::ActiveRecord::Relation]
|
24
|
+
if defined? ::ActiveRecord::Associations::CollectionProxy
|
25
|
+
klasses << ::ActiveRecord::Associations::CollectionProxy
|
26
|
+
else
|
27
|
+
klasses << ::ActiveRecord::Associations::AssociationCollection
|
33
28
|
end
|
34
29
|
|
35
30
|
# support pagination on associations and scopes
|
36
|
-
|
37
|
-
klass.send(:include, ActiveRecord)
|
38
|
-
end
|
31
|
+
klasses.each { |klass| klass.send(:include, ActiveRecord::Pagination) }
|
39
32
|
end
|
40
|
-
|
41
|
-
#
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
#
|
50
|
-
# A query for counting rows will automatically be generated if you don't
|
51
|
-
# supply <tt>:total_entries</tt>. If you experience problems with this
|
52
|
-
# generated SQL, you might want to perform the count manually in your
|
53
|
-
# application.
|
54
|
-
#
|
55
|
-
def paginate_by_sql(sql, options)
|
56
|
-
WillPaginate::Collection.create(*wp_parse_options(options)) do |pager|
|
57
|
-
query = sanitize_sql(sql.dup)
|
58
|
-
original_query = query.dup
|
59
|
-
# add limit, offset
|
60
|
-
query << " LIMIT #{pager.per_page} OFFSET #{pager.offset}"
|
61
|
-
# perfom the find
|
62
|
-
pager.replace find_by_sql(query)
|
63
|
-
|
64
|
-
unless pager.total_entries
|
65
|
-
count_query = original_query.sub /\bORDER\s+BY\s+[\w`,\s]+$/mi, ''
|
66
|
-
count_query = "SELECT COUNT(*) FROM (#{count_query})"
|
67
|
-
|
68
|
-
unless ['oracle', 'oci'].include?(self.connection.adapter_name.downcase)
|
69
|
-
count_query << ' AS count_table'
|
70
|
-
end
|
71
|
-
# perform the count query
|
72
|
-
pager.total_entries = count_by_sql(count_query)
|
33
|
+
|
34
|
+
# makes a Relation look like WillPaginate::Collection
|
35
|
+
module RelationMethods
|
36
|
+
attr_accessor :current_page
|
37
|
+
attr_writer :total_entries, :wp_count_options
|
38
|
+
|
39
|
+
def per_page(value = nil)
|
40
|
+
if value.nil? then limit_value
|
41
|
+
else limit(value)
|
73
42
|
end
|
74
43
|
end
|
75
|
-
end
|
76
44
|
|
77
|
-
|
45
|
+
# TODO: solve with less relation clones and code dups
|
46
|
+
def limit(num)
|
47
|
+
rel = super
|
48
|
+
if rel.current_page
|
49
|
+
rel.offset((rel.current_page-1) * rel.limit_value)
|
50
|
+
else
|
51
|
+
rel
|
52
|
+
end
|
53
|
+
end
|
78
54
|
|
79
|
-
|
80
|
-
|
81
|
-
|
55
|
+
def offset(value = nil)
|
56
|
+
if value.nil? then offset_value
|
57
|
+
else super(value)
|
58
|
+
end
|
59
|
+
end
|
82
60
|
|
83
|
-
|
84
|
-
|
85
|
-
|
61
|
+
def total_entries
|
62
|
+
@total_entries ||= begin
|
63
|
+
if loaded? and size < limit_value and (current_page == 1 or size > 0)
|
64
|
+
offset_value + size
|
65
|
+
else
|
66
|
+
excluded = [:order, :limit, :offset]
|
67
|
+
excluded << :includes unless eager_loading?
|
68
|
+
rel = self.except(*excluded)
|
69
|
+
# TODO: hack. decide whether to keep
|
70
|
+
rel = rel.apply_finder_options(@wp_count_options) if defined? @wp_count_options
|
71
|
+
rel.count
|
72
|
+
end
|
86
73
|
end
|
87
|
-
args << :all if args.empty?
|
88
74
|
end
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
75
|
+
|
76
|
+
# workaround for Active Record 3.0
|
77
|
+
def size
|
78
|
+
if !loaded? and limit_value
|
79
|
+
[super, limit_value].min
|
80
|
+
else
|
81
|
+
super
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def total_pages
|
86
|
+
(total_entries / limit_value.to_f).ceil
|
87
|
+
end
|
88
|
+
|
89
|
+
def clone
|
90
|
+
other = super
|
91
|
+
other.current_page = current_page unless other.current_page
|
92
|
+
other.total_entries = nil
|
93
|
+
other
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_a
|
97
|
+
if current_page.nil? then super # workaround for Active Record 3.0
|
98
|
+
else
|
99
|
+
::WillPaginate::Collection.create(current_page, limit_value) do |col|
|
100
|
+
col.replace super
|
101
|
+
col.total_entries ||= total_entries
|
102
|
+
end
|
103
|
+
end
|
96
104
|
end
|
97
105
|
end
|
98
106
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
counter.call
|
120
|
-
end
|
121
|
-
|
122
|
-
count.respond_to?(:length) ? count.length : count
|
107
|
+
module Pagination
|
108
|
+
def paginate(options)
|
109
|
+
pagenum, per_page, total = wp_parse_options(options)
|
110
|
+
count_options = options[:count]
|
111
|
+
options = options.except(:page, :per_page, :total_entries, :count)
|
112
|
+
rel = limit(per_page).page(pagenum)
|
113
|
+
rel = rel.apply_finder_options(options) if options.any?
|
114
|
+
rel.wp_count_options = count_options if count_options
|
115
|
+
rel
|
116
|
+
end
|
117
|
+
|
118
|
+
def page(num)
|
119
|
+
pagenum = num.nil? ? 1 : num.to_i
|
120
|
+
raise ::WillPaginate::InvalidPage, num, pagenum if pagenum < 1
|
121
|
+
rel = scoped.extending(RelationMethods)
|
122
|
+
rel = rel.offset((pagenum-1) * (rel.limit_value || per_page))
|
123
|
+
rel = rel.limit(per_page) unless rel.limit_value
|
124
|
+
rel.current_page = pagenum
|
125
|
+
rel
|
126
|
+
end
|
123
127
|
end
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
#
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
128
|
+
|
129
|
+
module BaseMethods
|
130
|
+
# Wraps +find_by_sql+ by simply adding LIMIT and OFFSET to your SQL string
|
131
|
+
# based on the params otherwise used by paginating finds: +page+ and
|
132
|
+
# +per_page+.
|
133
|
+
#
|
134
|
+
# Example:
|
135
|
+
#
|
136
|
+
# @developers = Developer.paginate_by_sql ['select * from developers where salary > ?', 80000],
|
137
|
+
# :page => params[:page], :per_page => 3
|
138
|
+
#
|
139
|
+
# A query for counting rows will automatically be generated if you don't
|
140
|
+
# supply <tt>:total_entries</tt>. If you experience problems with this
|
141
|
+
# generated SQL, you might want to perform the count manually in your
|
142
|
+
# application.
|
143
|
+
#
|
144
|
+
def paginate_by_sql(sql, options)
|
145
|
+
WillPaginate::Collection.create(*wp_parse_options(options)) do |pager|
|
146
|
+
query = sanitize_sql(sql.dup)
|
147
|
+
original_query = query.dup
|
148
|
+
# add limit, offset
|
149
|
+
query << " LIMIT #{pager.per_page} OFFSET #{pager.offset}"
|
150
|
+
# perfom the find
|
151
|
+
pager.replace find_by_sql(query)
|
152
|
+
|
153
|
+
unless pager.total_entries
|
154
|
+
count_query = original_query.sub /\bORDER\s+BY\s+[\w`,\s]+$/mi, ''
|
155
|
+
count_query = "SELECT COUNT(*) FROM (#{count_query})"
|
156
|
+
|
157
|
+
unless self.connection.adapter_name =~ /^(oracle|oci$)/i
|
158
|
+
count_query << ' AS count_table'
|
159
|
+
end
|
160
|
+
# perform the count query
|
161
|
+
pager.total_entries = count_by_sql(count_query)
|
162
|
+
end
|
138
163
|
end
|
139
|
-
else
|
140
|
-
excludees << :select
|
141
|
-
end
|
142
|
-
|
143
|
-
# count expects (almost) the same options as find
|
144
|
-
count_options = options.except *excludees
|
145
|
-
|
146
|
-
# merge the hash found in :count
|
147
|
-
# this allows you to specify :select, :order, or anything else just for the count query
|
148
|
-
count_options.update options[:count] if options[:count]
|
149
|
-
|
150
|
-
# forget about includes if they are irrelevant when counting
|
151
|
-
if count_options[:include] and count_options[:conditions].blank? and count_options[:group].blank?
|
152
|
-
count_options.delete :include
|
153
164
|
end
|
154
|
-
|
155
|
-
count_options
|
156
165
|
end
|
157
166
|
end
|
158
167
|
end
|
@@ -3,22 +3,20 @@ require 'will_paginate/collection'
|
|
3
3
|
|
4
4
|
module WillPaginate
|
5
5
|
class Railtie < Rails::Railtie
|
6
|
-
initializer "will_paginate
|
7
|
-
|
6
|
+
initializer "will_paginate" do |app|
|
7
|
+
ActiveSupport.on_load :active_record do
|
8
8
|
require 'will_paginate/finders/active_record'
|
9
9
|
WillPaginate::Finders::ActiveRecord.enable!
|
10
10
|
end
|
11
|
-
|
12
|
-
|
13
|
-
initializer "will_paginate.action_dispatch" do |app|
|
14
|
-
if defined? ::ActionDispatch::ShowExceptions
|
11
|
+
|
12
|
+
ActiveSupport.on_load :action_controller do
|
15
13
|
ActionDispatch::ShowExceptions.rescue_responses['WillPaginate::InvalidPage'] = :not_found
|
16
14
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
|
16
|
+
ActiveSupport.on_load :action_view do
|
17
|
+
require 'will_paginate/view_helpers/action_view'
|
18
|
+
include WillPaginate::ViewHelpers::ActionView
|
19
|
+
end
|
22
20
|
end
|
23
21
|
end
|
24
22
|
end
|
@@ -1,6 +1,4 @@
|
|
1
1
|
require 'will_paginate/view_helpers/base'
|
2
|
-
require 'action_view'
|
3
|
-
require 'action_pack/version'
|
4
2
|
require 'will_paginate/view_helpers/link_renderer'
|
5
3
|
|
6
4
|
module WillPaginate
|
@@ -63,8 +61,12 @@ module WillPaginate
|
|
63
61
|
# apply. Don't use the <tt>:id</tt> option; otherwise you'll finish with two
|
64
62
|
# blocks of pagination links sharing the same ID (which is invalid HTML).
|
65
63
|
def paginated_section(*args, &block)
|
66
|
-
pagination = will_paginate(*args)
|
67
|
-
|
64
|
+
pagination = will_paginate(*args)
|
65
|
+
if pagination
|
66
|
+
pagination + capture(&block) + pagination
|
67
|
+
else
|
68
|
+
capture(&block)
|
69
|
+
end
|
68
70
|
end
|
69
71
|
|
70
72
|
protected
|
@@ -86,7 +88,7 @@ WillPaginate::ViewHelpers::LinkRenderer.class_eval do
|
|
86
88
|
protected
|
87
89
|
|
88
90
|
def default_url_params
|
89
|
-
{
|
91
|
+
{}
|
90
92
|
end
|
91
93
|
|
92
94
|
def url(page)
|
@@ -131,4 +133,4 @@ WillPaginate::ViewHelpers::LinkRenderer.class_eval do
|
|
131
133
|
def parse_query_parameters(params)
|
132
134
|
Rack::Utils.parse_nested_query(params)
|
133
135
|
end
|
134
|
-
end
|
136
|
+
end
|
@@ -59,11 +59,13 @@ module WillPaginate
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def previous_page
|
62
|
-
|
62
|
+
num = @collection.current_page > 1 && @collection.current_page - 1
|
63
|
+
previous_or_next_page(num, @options[:previous_label], 'previous_page')
|
63
64
|
end
|
64
65
|
|
65
66
|
def next_page
|
66
|
-
|
67
|
+
num = @collection.current_page < @collection.total_pages && @collection.current_page + 1
|
68
|
+
previous_or_next_page(num, @options[:next_label], 'next_page')
|
67
69
|
end
|
68
70
|
|
69
71
|
def previous_or_next_page(page, text, classname)
|
@@ -107,8 +109,8 @@ module WillPaginate
|
|
107
109
|
|
108
110
|
def rel_value(page)
|
109
111
|
case page
|
110
|
-
when @collection.
|
111
|
-
when @collection.
|
112
|
+
when @collection.current_page - 1; 'prev' + (page == 1 ? ' start' : '')
|
113
|
+
when @collection.current_page + 1; 'next'
|
112
114
|
when 1; 'start'
|
113
115
|
end
|
114
116
|
end
|
data/spec/console
CHANGED
@@ -1,8 +1,4 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
3
|
-
|
4
|
-
|
5
|
-
libs << 'irb/completion'
|
6
|
-
libs << 'console_fixtures'
|
7
|
-
|
8
|
-
exec "#{irb} -Ilib:spec#{libs.map{ |l| " -r #{l}" }.join} --simple-prompt"
|
3
|
+
opts = %w[--simple-prompt -rirb/completion -rconsole_fixtures]
|
4
|
+
exec 'bundle', 'exec', irb, '-Ilib:spec', *opts
|
data/spec/console_fixtures.rb
CHANGED
@@ -1,8 +1,30 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.setup
|
3
|
+
|
1
4
|
require 'will_paginate/finders/active_record'
|
2
5
|
require 'finders/activerecord_test_connector'
|
6
|
+
|
3
7
|
ActiverecordTestConnector.setup
|
4
8
|
|
9
|
+
windows = RUBY_PLATFORM =~ /(:?mswin|mingw)/
|
10
|
+
# used just for the `color` method
|
11
|
+
log_subscriber = ActiveSupport::LogSubscriber.log_subscribers.first
|
12
|
+
|
13
|
+
IGNORE_SQL = /\b(sqlite_master|sqlite_version)\b|^(CREATE TABLE|PRAGMA)\b/
|
14
|
+
|
15
|
+
ActiveSupport::Notifications.subscribe(/^sql\./) do |*args|
|
16
|
+
data = args.last
|
17
|
+
unless data[:name] =~ /^Fixture/ or data[:sql] =~ IGNORE_SQL
|
18
|
+
if windows
|
19
|
+
puts data[:sql]
|
20
|
+
else
|
21
|
+
puts log_subscriber.send(:color, data[:sql], :cyan)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
5
26
|
# load all fixtures
|
6
|
-
Fixtures.create_fixtures
|
27
|
+
ActiverecordTestConnector::Fixtures.create_fixtures \
|
28
|
+
ActiverecordTestConnector::FIXTURES_PATH, ActiveRecord::Base.connection.tables
|
7
29
|
|
8
|
-
|
30
|
+
WillPaginate::Finders::ActiveRecord.enable!
|
@@ -17,7 +17,7 @@ describe WillPaginate::Finders::ActiveRecord do
|
|
17
17
|
|
18
18
|
it "should paginate" do
|
19
19
|
lambda {
|
20
|
-
users = User.paginate(:page => 1, :per_page => 5)
|
20
|
+
users = User.paginate(:page => 1, :per_page => 5).to_a
|
21
21
|
users.length.should == 5
|
22
22
|
}.should run_queries(2)
|
23
23
|
end
|
@@ -28,6 +28,58 @@ describe WillPaginate::Finders::ActiveRecord do
|
|
28
28
|
}.should raise_error(ArgumentError)
|
29
29
|
end
|
30
30
|
|
31
|
+
describe "relation" do
|
32
|
+
it "should return a relation" do
|
33
|
+
rel = nil
|
34
|
+
lambda {
|
35
|
+
rel = Developer.paginate(:page => 1)
|
36
|
+
rel.per_page.should == 10
|
37
|
+
rel.current_page.should == 1
|
38
|
+
}.should run_queries(0)
|
39
|
+
|
40
|
+
lambda {
|
41
|
+
rel.total_pages.should == 2
|
42
|
+
}.should run_queries(1)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should keep per-class per_page number" do
|
46
|
+
rel = Developer.order('id').paginate(:page => 1)
|
47
|
+
rel.per_page.should == 10
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should be able to change per_page number" do
|
51
|
+
rel = Developer.order('id').paginate(:page => 1).limit(5)
|
52
|
+
rel.per_page.should == 5
|
53
|
+
end
|
54
|
+
|
55
|
+
it "supports the page() method" do
|
56
|
+
rel = Developer.page('1').order('id')
|
57
|
+
rel.current_page.should == 1
|
58
|
+
rel.per_page.should == 10
|
59
|
+
rel.offset.should == 0
|
60
|
+
|
61
|
+
rel = rel.limit(5).page(2)
|
62
|
+
rel.per_page.should == 5
|
63
|
+
rel.offset.should == 5
|
64
|
+
end
|
65
|
+
|
66
|
+
it "raises on invalid page number" do
|
67
|
+
lambda {
|
68
|
+
Developer.page('foo')
|
69
|
+
}.should raise_error(ArgumentError)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "supports first limit() then page()" do
|
73
|
+
rel = Developer.limit(3).page(3)
|
74
|
+
rel.offset.should == 6
|
75
|
+
end
|
76
|
+
|
77
|
+
it "supports first page() then limit()" do
|
78
|
+
rel = Developer.page(3).limit(3)
|
79
|
+
rel.offset.should == 6
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
31
83
|
describe "counting" do
|
32
84
|
it "should not accept :count parameter" do
|
33
85
|
pending
|
@@ -111,6 +163,7 @@ describe WillPaginate::Finders::ActiveRecord do
|
|
111
163
|
it "should get first page of Topics with a single query" do
|
112
164
|
lambda {
|
113
165
|
result = Topic.paginate :page => nil
|
166
|
+
result.to_a # trigger loading of records
|
114
167
|
result.current_page.should == 1
|
115
168
|
result.total_pages.should == 1
|
116
169
|
result.size.should == 4
|
@@ -156,11 +209,8 @@ describe WillPaginate::Finders::ActiveRecord do
|
|
156
209
|
it "should paginate with :include and :order" do
|
157
210
|
result = nil
|
158
211
|
lambda {
|
159
|
-
result = Topic.paginate
|
160
|
-
:
|
161
|
-
:include => :replies,
|
162
|
-
:order => 'replies.created_at asc, topics.created_at asc',
|
163
|
-
:per_page => 10
|
212
|
+
result = Topic.paginate(:page => 1, :include => :replies, :per_page => 10,
|
213
|
+
:order => 'replies.created_at asc, topics.created_at asc').to_a
|
164
214
|
}.should run_queries(2)
|
165
215
|
|
166
216
|
expected = Topic.find :all,
|
@@ -174,17 +224,19 @@ describe WillPaginate::Finders::ActiveRecord do
|
|
174
224
|
|
175
225
|
it "should remove :include for count" do
|
176
226
|
lambda {
|
177
|
-
Developer.paginate
|
178
|
-
$query_sql.last.should_not
|
179
|
-
}.should run_queries(4)
|
227
|
+
Developer.paginate(:page => 1, :per_page => 1, :include => :projects).to_a
|
228
|
+
$query_sql.last.should_not =~ /\bJOIN\b/
|
229
|
+
}.should run_queries(3..4)
|
180
230
|
end
|
181
231
|
|
182
232
|
it "should keep :include for count when they are referenced in :conditions" do
|
183
|
-
Developer.
|
184
|
-
|
233
|
+
Developer.paginate(
|
234
|
+
:page => 1, :per_page => 1,
|
235
|
+
:include => :projects,
|
236
|
+
:conditions => 'projects.id > 2'
|
237
|
+
).to_a
|
185
238
|
|
186
|
-
|
187
|
-
:include => :projects, :conditions => 'projects.id > 2'
|
239
|
+
$query_sql.last.should =~ /\bJOIN\b/
|
188
240
|
end
|
189
241
|
|
190
242
|
describe "associations" do
|
@@ -199,7 +251,7 @@ describe WillPaginate::Finders::ActiveRecord do
|
|
199
251
|
|
200
252
|
expected = Topic.find :all,
|
201
253
|
:include => 'replies',
|
202
|
-
:conditions => ["project_id =
|
254
|
+
:conditions => ["project_id = ? AND replies.content LIKE ?", project.id, 'Nice%'],
|
203
255
|
:limit => 10
|
204
256
|
|
205
257
|
result.should == expected
|
@@ -218,7 +270,7 @@ describe WillPaginate::Finders::ActiveRecord do
|
|
218
270
|
}.should run_queries(2)
|
219
271
|
|
220
272
|
# with explicit order
|
221
|
-
result = dhh.projects.paginate(:page => 1
|
273
|
+
result = dhh.projects.paginate(:page => 1).reorder('projects.id')
|
222
274
|
result.should == expected_id_ordered
|
223
275
|
result.total_entries.should == 2
|
224
276
|
|
@@ -226,7 +278,7 @@ describe WillPaginate::Finders::ActiveRecord do
|
|
226
278
|
dhh.projects.find(:all, :order => 'projects.id', :limit => 4)
|
227
279
|
}.should_not raise_error
|
228
280
|
|
229
|
-
result = dhh.projects.paginate(:page => 1, :
|
281
|
+
result = dhh.projects.paginate(:page => 1, :per_page => 4).reorder('projects.id')
|
230
282
|
result.should == expected_id_ordered
|
231
283
|
|
232
284
|
# has_many with implicit order
|
@@ -234,7 +286,7 @@ describe WillPaginate::Finders::ActiveRecord do
|
|
234
286
|
expected = replies(:spam, :witty_retort)
|
235
287
|
# FIXME: wow, this is ugly
|
236
288
|
topic.replies.paginate(:page => 1).map(&:id).sort.should == expected.map(&:id).sort
|
237
|
-
topic.replies.paginate(:page => 1
|
289
|
+
topic.replies.paginate(:page => 1).reorder('replies.id ASC').should == expected.reverse
|
238
290
|
end
|
239
291
|
|
240
292
|
it "should paginate through association extension" do
|
@@ -253,7 +305,8 @@ describe WillPaginate::Finders::ActiveRecord do
|
|
253
305
|
join_sql = 'LEFT JOIN developers_projects ON users.id = developers_projects.developer_id'
|
254
306
|
|
255
307
|
lambda {
|
256
|
-
result = Developer.paginate
|
308
|
+
result = Developer.paginate(:page => 1, :joins => join_sql, :conditions => 'project_id = 1')
|
309
|
+
result.to_a # trigger loading of records
|
257
310
|
result.size.should == 2
|
258
311
|
developer_names = result.map(&:name)
|
259
312
|
developer_names.should include('David')
|
@@ -262,8 +315,8 @@ describe WillPaginate::Finders::ActiveRecord do
|
|
262
315
|
|
263
316
|
lambda {
|
264
317
|
expected = result.to_a
|
265
|
-
result = Developer.paginate
|
266
|
-
|
318
|
+
result = Developer.paginate(:page => 1, :joins => join_sql,
|
319
|
+
:conditions => 'project_id = 1', :count => { :select => "users.id" }).to_a
|
267
320
|
result.should == expected
|
268
321
|
result.total_entries.should == 2
|
269
322
|
}.should run_queries(1)
|
@@ -272,8 +325,8 @@ describe WillPaginate::Finders::ActiveRecord do
|
|
272
325
|
it "should paginate with group" do
|
273
326
|
result = nil
|
274
327
|
lambda {
|
275
|
-
result = Developer.paginate
|
276
|
-
|
328
|
+
result = Developer.paginate(:page => 1, :per_page => 10,
|
329
|
+
:group => 'salary', :select => 'salary', :order => 'salary').to_a
|
277
330
|
}.should run_queries(1)
|
278
331
|
|
279
332
|
expected = users(:david, :jamis, :dev_10, :poor_jamis).map(&:salary).sort
|
@@ -337,12 +390,10 @@ describe WillPaginate::Finders::ActiveRecord do
|
|
337
390
|
}.should_not raise_error
|
338
391
|
end
|
339
392
|
|
340
|
-
it "should paginate an array of IDs" do
|
393
|
+
it "should not paginate an array of IDs" do
|
341
394
|
lambda {
|
342
|
-
|
343
|
-
|
344
|
-
result.total_entries.should == 8
|
345
|
-
}.should run_queries(1)
|
395
|
+
Developer.paginate((1..8).to_a, :per_page => 3, :page => 2, :order => 'id')
|
396
|
+
}.should raise_error(ArgumentError)
|
346
397
|
end
|
347
398
|
|
348
399
|
protected
|
@@ -351,6 +402,18 @@ describe WillPaginate::Finders::ActiveRecord do
|
|
351
402
|
QueryCountMatcher.new(num)
|
352
403
|
end
|
353
404
|
|
405
|
+
def show_queries(&block)
|
406
|
+
counter = QueryCountMatcher.new(nil)
|
407
|
+
counter.run block
|
408
|
+
ensure
|
409
|
+
queries = counter.performed_queries
|
410
|
+
if queries.any?
|
411
|
+
puts queries
|
412
|
+
else
|
413
|
+
puts "no queries"
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
354
417
|
end
|
355
418
|
|
356
419
|
class QueryCountMatcher
|
@@ -359,12 +422,26 @@ class QueryCountMatcher
|
|
359
422
|
end
|
360
423
|
|
361
424
|
def matches?(block)
|
425
|
+
run(block)
|
426
|
+
|
427
|
+
if @expected_count.respond_to? :include?
|
428
|
+
@expected_count.include? @count
|
429
|
+
else
|
430
|
+
@count == @expected_count
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
def run(block)
|
362
435
|
$query_count = 0
|
363
436
|
$query_sql = []
|
364
437
|
block.call
|
365
|
-
|
438
|
+
ensure
|
439
|
+
@queries = $query_sql.dup
|
366
440
|
@count = $query_count
|
367
|
-
|
441
|
+
end
|
442
|
+
|
443
|
+
def performed_queries
|
444
|
+
@queries
|
368
445
|
end
|
369
446
|
|
370
447
|
def failure_message
|
@@ -372,6 +449,6 @@ class QueryCountMatcher
|
|
372
449
|
end
|
373
450
|
|
374
451
|
def negative_failure_message
|
375
|
-
"expected query count not to be #{
|
452
|
+
"expected query count not to be #{@expected_count}"
|
376
453
|
end
|
377
454
|
end
|
@@ -1,21 +1,35 @@
|
|
1
1
|
require 'active_record'
|
2
|
-
require 'active_record/version'
|
3
2
|
require 'active_record/fixtures'
|
4
3
|
require 'active_support/multibyte' # needed for Ruby 1.9.1
|
5
4
|
|
6
|
-
$query_count =
|
5
|
+
$query_count = 0
|
6
|
+
$query_sql = []
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
ignore_sql = /^(?:PRAGMA|SELECT (?:currval|CAST|@@IDENTITY|@@ROWCOUNT)|SHOW FIELDS)\b|\bFROM sqlite_master\b/
|
9
|
+
|
10
|
+
ActiveSupport::Notifications.subscribe(/^sql\./) do |*args|
|
11
|
+
payload = args.last
|
12
|
+
unless payload[:name] =~ /^Fixture/ or payload[:sql] =~ ignore_sql
|
13
|
+
$query_count += 1
|
14
|
+
$query_sql << payload[:sql]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module ActiverecordTestConnector
|
19
|
+
extend self
|
20
|
+
|
21
|
+
attr_accessor :able_to_connect
|
22
|
+
attr_accessor :connected
|
11
23
|
|
12
24
|
FIXTURES_PATH = File.expand_path('../../fixtures', __FILE__)
|
13
25
|
|
26
|
+
Fixtures = defined?(ActiveRecord::Fixtures) ? ActiveRecord::Fixtures : ::Fixtures
|
27
|
+
|
14
28
|
# Set our defaults
|
15
29
|
self.connected = false
|
16
30
|
self.able_to_connect = true
|
17
31
|
|
18
|
-
def
|
32
|
+
def setup
|
19
33
|
unless self.connected || !self.able_to_connect
|
20
34
|
setup_connection
|
21
35
|
load_schema
|
@@ -29,54 +43,31 @@ class ActiverecordTestConnector
|
|
29
43
|
|
30
44
|
private
|
31
45
|
|
32
|
-
def
|
46
|
+
def add_load_path(path)
|
33
47
|
dep = defined?(ActiveSupport::Dependencies) ? ActiveSupport::Dependencies : ::Dependencies
|
34
48
|
dep.autoload_paths.unshift path
|
35
49
|
end
|
36
50
|
|
37
|
-
def
|
51
|
+
def setup_connection
|
38
52
|
db = ENV['DB'].blank?? 'sqlite3' : ENV['DB']
|
39
53
|
|
40
54
|
configurations = YAML.load_file(File.expand_path('../../database.yml', __FILE__))
|
41
55
|
raise "no configuration for '#{db}'" unless configurations.key? db
|
42
56
|
configuration = configurations[db]
|
43
57
|
|
44
|
-
ActiveRecord::Base.logger = Logger.new(STDOUT) if $0 == 'irb'
|
58
|
+
# ActiveRecord::Base.logger = Logger.new(STDOUT) if $0 == 'irb'
|
45
59
|
puts "using #{configuration['adapter']} adapter"
|
46
60
|
|
47
61
|
ActiveRecord::Base.configurations = { db => configuration }
|
48
62
|
ActiveRecord::Base.establish_connection(db)
|
49
|
-
prepare ActiveRecord::Base.connection
|
50
63
|
end
|
51
64
|
|
52
|
-
def
|
65
|
+
def load_schema
|
53
66
|
ActiveRecord::Base.silence do
|
54
67
|
ActiveRecord::Migration.verbose = false
|
55
68
|
load File.join(FIXTURES_PATH, 'schema.rb')
|
56
69
|
end
|
57
70
|
end
|
58
|
-
|
59
|
-
def self.prepare(conn)
|
60
|
-
class << conn
|
61
|
-
IGNORED_SQL = /^(?:PRAGMA|SELECT (?:currval|CAST|@@IDENTITY|@@ROWCOUNT)|SHOW FIELDS)\b/
|
62
|
-
|
63
|
-
def execute_with_counting(sql, name = nil, &block)
|
64
|
-
if $query_count and IGNORED_SQL !~ sql
|
65
|
-
$query_count += 1
|
66
|
-
$query_sql << sql
|
67
|
-
end
|
68
|
-
execute_without_counting(sql, name, &block)
|
69
|
-
end
|
70
|
-
|
71
|
-
alias_method_chain :execute, :counting
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def self.show_sql
|
76
|
-
ActiveSupport::Notifications.subscribe('active_record.sql') do |*args|
|
77
|
-
puts args.last[:sql]
|
78
|
-
end
|
79
|
-
end
|
80
71
|
|
81
72
|
module FixtureSetup
|
82
73
|
def fixtures(*tables)
|
@@ -1,8 +1,14 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'will_paginate/finders/data_mapper'
|
3
|
-
require File.expand_path('../data_mapper_test_connector', __FILE__)
|
4
2
|
|
5
|
-
|
3
|
+
begin
|
4
|
+
require 'will_paginate/finders/data_mapper'
|
5
|
+
require File.expand_path('../data_mapper_test_connector', __FILE__)
|
6
|
+
rescue LoadError => error
|
7
|
+
warn "Error running DataMapper specs: #{error.message}"
|
8
|
+
datamapper_loaded = false
|
9
|
+
else
|
10
|
+
datamapper_loaded = true
|
11
|
+
end
|
6
12
|
|
7
13
|
describe WillPaginate::Finders::DataMapper do
|
8
14
|
|
@@ -59,4 +65,4 @@ describe WillPaginate::Finders::DataMapper do
|
|
59
65
|
end
|
60
66
|
end
|
61
67
|
|
62
|
-
end
|
68
|
+
end if datamapper_loaded
|
data/spec/finders/sequel_spec.rb
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
|
3
|
-
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'will_paginate/finders/sequel'
|
5
|
+
require File.expand_path('../sequel_test_connector', __FILE__)
|
6
|
+
rescue LoadError, ArgumentError => error
|
7
|
+
warn "Error running Sequel specs: #{error.message}"
|
8
|
+
sequel_loaded = false
|
9
|
+
else
|
10
|
+
sequel_loaded = true
|
11
|
+
end
|
4
12
|
|
5
13
|
describe Sequel::Dataset::Pagination, 'extension' do
|
6
14
|
|
@@ -50,4 +58,4 @@ describe Sequel::Dataset::Pagination, 'extension' do
|
|
50
58
|
end
|
51
59
|
end
|
52
60
|
|
53
|
-
end
|
61
|
+
end if sequel_loaded
|
data/spec/fixtures/replies.yml
CHANGED
@@ -2,28 +2,28 @@ witty_retort:
|
|
2
2
|
id: 1
|
3
3
|
topic_id: 1
|
4
4
|
content: Birdman is better!
|
5
|
-
created_at: <%= 6.hours.ago.to_s(:db) %>
|
5
|
+
created_at: <%= 6.hours.ago.utc.to_s(:db) %>
|
6
6
|
|
7
7
|
another:
|
8
8
|
id: 2
|
9
9
|
topic_id: 2
|
10
10
|
content: Nuh uh!
|
11
|
-
created_at: <%= 1.hour.ago.to_s(:db) %>
|
11
|
+
created_at: <%= 1.hour.ago.utc.to_s(:db) %>
|
12
12
|
|
13
13
|
spam:
|
14
14
|
id: 3
|
15
15
|
topic_id: 1
|
16
16
|
content: Nice site!
|
17
|
-
created_at: <%= 1.hour.ago.to_s(:db) %>
|
17
|
+
created_at: <%= 1.hour.ago.utc.to_s(:db) %>
|
18
18
|
|
19
19
|
decisive:
|
20
20
|
id: 4
|
21
21
|
topic_id: 4
|
22
22
|
content: "I'm getting to the bottom of this"
|
23
|
-
created_at: <%= 30.minutes.ago.to_s(:db) %>
|
23
|
+
created_at: <%= 30.minutes.ago.utc.to_s(:db) %>
|
24
24
|
|
25
25
|
brave:
|
26
26
|
id: 5
|
27
27
|
topic_id: 4
|
28
28
|
content: "AR doesn't scare me a bit"
|
29
|
-
created_at: <%= 10.minutes.ago.to_s(:db) %>
|
29
|
+
created_at: <%= 10.minutes.ago.utc.to_s(:db) %>
|
data/spec/fixtures/reply.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
class Reply < ActiveRecord::Base
|
2
2
|
belongs_to :topic, :include => [:replies]
|
3
3
|
|
4
|
-
scope :recent,
|
5
|
-
|
4
|
+
scope :recent,
|
5
|
+
:conditions => ['replies.created_at > ?', 15.minutes.ago],
|
6
|
+
:order => 'replies.created_at DESC'
|
7
|
+
|
6
8
|
validates_presence_of :content
|
7
9
|
end
|
data/spec/fixtures/topics.yml
CHANGED
@@ -3,7 +3,7 @@ futurama:
|
|
3
3
|
title: Isnt futurama awesome?
|
4
4
|
subtitle: It really is, isnt it.
|
5
5
|
content: I like futurama
|
6
|
-
created_at: <%= 1.day.ago.to_s(:db) %>
|
6
|
+
created_at: <%= 1.day.ago.utc.to_s(:db) %>
|
7
7
|
updated_at:
|
8
8
|
|
9
9
|
harvey_birdman:
|
@@ -11,7 +11,7 @@ harvey_birdman:
|
|
11
11
|
title: Harvey Birdman is the king of all men
|
12
12
|
subtitle: yup
|
13
13
|
content: He really is
|
14
|
-
created_at: <%= 2.hours.ago.to_s(:db) %>
|
14
|
+
created_at: <%= 2.hours.ago.utc.to_s(:db) %>
|
15
15
|
updated_at:
|
16
16
|
|
17
17
|
rails:
|
@@ -20,11 +20,11 @@ rails:
|
|
20
20
|
title: Rails is nice
|
21
21
|
subtitle: It makes me happy
|
22
22
|
content: except when I have to hack internals to fix pagination. even then really.
|
23
|
-
created_at: <%= 20.minutes.ago.to_s(:db) %>
|
23
|
+
created_at: <%= 20.minutes.ago.utc.to_s(:db) %>
|
24
24
|
|
25
25
|
ar:
|
26
26
|
id: 4
|
27
27
|
project_id: 1
|
28
28
|
title: ActiveRecord sometimes freaks me out
|
29
29
|
content: "I mean, what's the deal with eager loading?"
|
30
|
-
created_at: <%= 15.minutes.ago.to_s(:db) %>
|
30
|
+
created_at: <%= 15.minutes.ago.utc.to_s(:db) %>
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
require 'spec/autorun'
|
1
|
+
require 'rspec'
|
2
|
+
require File.expand_path('../view_helpers/view_example_group', __FILE__)
|
4
3
|
|
5
4
|
module MyExtras
|
6
5
|
protected
|
@@ -22,7 +21,7 @@ module MyExtras
|
|
22
21
|
end
|
23
22
|
end
|
24
23
|
|
25
|
-
|
24
|
+
RSpec.configure do |config|
|
26
25
|
# config.include My::Pony, My::Horse, :type => :farm
|
27
26
|
config.include MyExtras
|
28
27
|
# config.predicate_matchers[:swim] = :can_swim?
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'active_support/rescuable' # needed for Ruby 1.9.1
|
3
3
|
require 'action_controller'
|
4
|
-
require 'view_helpers/view_example_group'
|
5
4
|
require 'will_paginate/view_helpers/action_view'
|
6
5
|
require 'will_paginate/collection'
|
7
6
|
|
@@ -311,6 +310,14 @@ class DummyController
|
|
311
310
|
def params
|
312
311
|
@request.params
|
313
312
|
end
|
313
|
+
|
314
|
+
def env
|
315
|
+
{}
|
316
|
+
end
|
317
|
+
|
318
|
+
def _prefixes
|
319
|
+
[]
|
320
|
+
end
|
314
321
|
end
|
315
322
|
|
316
323
|
class IbocorpController < DummyController
|
@@ -349,6 +356,11 @@ class DummyRequest
|
|
349
356
|
def host_with_port
|
350
357
|
'example.com'
|
351
358
|
end
|
359
|
+
alias host host_with_port
|
360
|
+
|
361
|
+
def optional_port
|
362
|
+
''
|
363
|
+
end
|
352
364
|
|
353
365
|
def protocol
|
354
366
|
'http:'
|
@@ -1,6 +1,7 @@
|
|
1
|
+
require 'active_support'
|
1
2
|
require 'action_dispatch/testing/assertions'
|
2
3
|
|
3
|
-
|
4
|
+
module ViewExampleGroup
|
4
5
|
|
5
6
|
include ActionDispatch::Assertions::SelectorAssertions
|
6
7
|
|
@@ -38,8 +39,8 @@ class ViewExampleGroup < Spec::Example::ExampleGroup
|
|
38
39
|
def validate_page_numbers(expected, links, param_name = :page)
|
39
40
|
param_pattern = /\W#{Regexp.escape(param_name.to_s)}=([^&]*)/
|
40
41
|
|
41
|
-
links.map { |
|
42
|
-
|
42
|
+
links.map { |el|
|
43
|
+
unescape_href(el) =~ param_pattern
|
43
44
|
$1 ? $1.to_i : $1
|
44
45
|
}.should == expected
|
45
46
|
end
|
@@ -52,9 +53,10 @@ class ViewExampleGroup < Spec::Example::ExampleGroup
|
|
52
53
|
pages = [] if numbers
|
53
54
|
|
54
55
|
links.each do |el|
|
55
|
-
|
56
|
+
href = unescape_href(el)
|
57
|
+
href.should =~ pattern
|
56
58
|
if numbers
|
57
|
-
|
59
|
+
href =~ pattern
|
58
60
|
pages << ($1.nil?? nil : $1.to_i)
|
59
61
|
end
|
60
62
|
end
|
@@ -65,10 +67,14 @@ class ViewExampleGroup < Spec::Example::ExampleGroup
|
|
65
67
|
def assert_no_links_match(pattern)
|
66
68
|
assert_select 'div.pagination a[href]' do |elements|
|
67
69
|
elements.each do |el|
|
68
|
-
el
|
70
|
+
unescape_href(el).should_not =~ pattern
|
69
71
|
end
|
70
72
|
end
|
71
73
|
end
|
74
|
+
|
75
|
+
def unescape_href(el)
|
76
|
+
CGI.unescape CGI.unescapeHTML(el['href'])
|
77
|
+
end
|
72
78
|
|
73
79
|
def build_message(message, pattern, *args)
|
74
80
|
built_message = pattern.dup
|
@@ -80,7 +86,11 @@ class ViewExampleGroup < Spec::Example::ExampleGroup
|
|
80
86
|
|
81
87
|
end
|
82
88
|
|
83
|
-
|
89
|
+
RSpec.configure do |config|
|
90
|
+
config.include ViewExampleGroup, :type => :view, :example_group => {
|
91
|
+
:file_path => %r{spec/view_helpers/}
|
92
|
+
}
|
93
|
+
end
|
84
94
|
|
85
95
|
module HTML
|
86
96
|
Node.class_eval do
|
metadata
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: will_paginate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
segments:
|
7
|
-
- 3
|
8
|
-
- 0
|
9
|
-
- pre2
|
10
|
-
version: 3.0.pre2
|
4
|
+
prerelease: 4
|
5
|
+
version: 3.0.pre4
|
11
6
|
platform: ruby
|
12
7
|
authors:
|
13
8
|
- "Mislav Marohni\xC4\x87"
|
@@ -15,8 +10,7 @@ autorequire:
|
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
12
|
|
18
|
-
date: 2010-02-05 00:00:00
|
19
|
-
default_executable:
|
13
|
+
date: 2010-02-05 00:00:00 Z
|
20
14
|
dependencies: []
|
21
15
|
|
22
16
|
description: The will_paginate library provides a simple, yet powerful and extensible API for pagination and rendering of page links in web application templates.
|
@@ -74,10 +68,7 @@ files:
|
|
74
68
|
- spec/fixtures/topics.yml
|
75
69
|
- spec/fixtures/user.rb
|
76
70
|
- spec/fixtures/users.yml
|
77
|
-
- spec/rcov.opts
|
78
|
-
- spec/spec.opts
|
79
71
|
- spec/spec_helper.rb
|
80
|
-
- spec/tasks.rake
|
81
72
|
- spec/view_helpers/action_view_spec.rb
|
82
73
|
- spec/view_helpers/base_spec.rb
|
83
74
|
- spec/view_helpers/link_renderer_base_spec.rb
|
@@ -85,7 +76,6 @@ files:
|
|
85
76
|
- README.rdoc
|
86
77
|
- LICENSE
|
87
78
|
- CHANGELOG.rdoc
|
88
|
-
has_rdoc: true
|
89
79
|
homepage: http://github.com/mislav/will_paginate/wikis
|
90
80
|
licenses: []
|
91
81
|
|
@@ -101,25 +91,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
101
91
|
requirements:
|
102
92
|
- - ">="
|
103
93
|
- !ruby/object:Gem::Version
|
104
|
-
hash: 3
|
105
|
-
segments:
|
106
|
-
- 0
|
107
94
|
version: "0"
|
108
95
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
96
|
none: false
|
110
97
|
requirements:
|
111
98
|
- - ">"
|
112
99
|
- !ruby/object:Gem::Version
|
113
|
-
hash: 25
|
114
|
-
segments:
|
115
|
-
- 1
|
116
|
-
- 3
|
117
|
-
- 1
|
118
100
|
version: 1.3.1
|
119
101
|
requirements: []
|
120
102
|
|
121
103
|
rubyforge_project:
|
122
|
-
rubygems_version: 1.
|
104
|
+
rubygems_version: 1.8.5
|
123
105
|
signing_key:
|
124
106
|
specification_version: 3
|
125
107
|
summary: Adaptive pagination plugin for web frameworks and other applications
|
data/spec/rcov.opts
DELETED
data/spec/spec.opts
DELETED
data/spec/tasks.rake
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
require 'spec/rake/spectask'
|
2
|
-
|
3
|
-
spec_opts = 'spec/spec.opts'
|
4
|
-
|
5
|
-
desc 'Run framework-agnostic specs'
|
6
|
-
Spec::Rake::SpecTask.new(:spec) do |t|
|
7
|
-
t.libs << 'spec'
|
8
|
-
t.spec_opts = ['--options', spec_opts]
|
9
|
-
t.spec_files = FileList.new('spec/**/*_spec.rb') do |files|
|
10
|
-
files.exclude(/\b(active_record|active_resource|action_view|data_mapper|sequel)_/)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
namespace :spec do
|
15
|
-
desc 'Run specs for core, ActiveRecord and ActionView'
|
16
|
-
Spec::Rake::SpecTask.new(:rails) do |t|
|
17
|
-
t.libs << 'spec'
|
18
|
-
t.spec_opts = ['--options', spec_opts]
|
19
|
-
t.spec_files = FileList.new('spec/**/*_spec.rb') do |files|
|
20
|
-
files.exclude(/\b(data_mapper|sequel)_/)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
desc 'Run specs for DataMapper'
|
25
|
-
Spec::Rake::SpecTask.new(:datamapper) do |t|
|
26
|
-
t.libs << 'spec'
|
27
|
-
t.spec_opts = ['--options', spec_opts]
|
28
|
-
t.spec_files = FileList.new('spec/finders_spec.rb', 'spec/finders/data_mapper_spec.rb')
|
29
|
-
end
|
30
|
-
|
31
|
-
desc 'Run specs for Sequel'
|
32
|
-
Spec::Rake::SpecTask.new(:sequel) do |t|
|
33
|
-
t.libs << 'spec'
|
34
|
-
t.spec_opts = ['--options', spec_opts]
|
35
|
-
t.spec_files = FileList.new('spec/finders_spec.rb', 'spec/finders/sequel_spec.rb')
|
36
|
-
end
|
37
|
-
|
38
|
-
desc 'Analyze spec coverage with RCov'
|
39
|
-
Spec::Rake::SpecTask.new(:rcov) do |t|
|
40
|
-
t.libs << 'spec'
|
41
|
-
t.spec_opts = ['--options', spec_opts]
|
42
|
-
t.rcov = true
|
43
|
-
t.rcov_opts = lambda do
|
44
|
-
IO.readlines('spec/rcov.opts').map { |l| l.chomp.split(" ") }.flatten
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
desc 'Print Specdoc for all specs'
|
49
|
-
Spec::Rake::SpecTask.new(:doc) do |t|
|
50
|
-
t.libs << 'spec'
|
51
|
-
t.spec_opts = ['--format', 'specdoc', '--dry-run']
|
52
|
-
end
|
53
|
-
|
54
|
-
desc 'Generate HTML report'
|
55
|
-
Spec::Rake::SpecTask.new(:html) do |t|
|
56
|
-
t.libs << 'spec'
|
57
|
-
t.spec_opts = ['--format', 'html:doc/spec_results.html', '--diff']
|
58
|
-
t.fail_on_error = false
|
59
|
-
end
|
60
|
-
end
|