hobo_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.
- checksums.yaml +15 -0
- data/LICENSE +18 -0
- data/README.md +61 -0
- data/Rakefile +25 -0
- data/lib/will_paginate.rb +25 -0
- data/lib/will_paginate/active_record.rb +216 -0
- data/lib/will_paginate/array.rb +57 -0
- data/lib/will_paginate/collection.rb +149 -0
- data/lib/will_paginate/core_ext.rb +30 -0
- data/lib/will_paginate/data_mapper.rb +95 -0
- data/lib/will_paginate/deprecation.rb +55 -0
- data/lib/will_paginate/i18n.rb +22 -0
- data/lib/will_paginate/locale/en.yml +33 -0
- data/lib/will_paginate/page_number.rb +57 -0
- data/lib/will_paginate/per_page.rb +27 -0
- data/lib/will_paginate/railtie.rb +68 -0
- data/lib/will_paginate/sequel.rb +39 -0
- data/lib/will_paginate/version.rb +9 -0
- data/lib/will_paginate/view_helpers.rb +161 -0
- data/lib/will_paginate/view_helpers/action_view.rb +148 -0
- data/lib/will_paginate/view_helpers/link_renderer.rb +132 -0
- data/lib/will_paginate/view_helpers/link_renderer_base.rb +77 -0
- data/lib/will_paginate/view_helpers/merb.rb +26 -0
- data/lib/will_paginate/view_helpers/sinatra.rb +41 -0
- data/spec/ci.rb +29 -0
- data/spec/collection_spec.rb +139 -0
- data/spec/console +12 -0
- data/spec/console_fixtures.rb +28 -0
- data/spec/database.yml +22 -0
- data/spec/finders/active_record_spec.rb +543 -0
- data/spec/finders/activerecord_test_connector.rb +113 -0
- data/spec/finders/data_mapper_spec.rb +103 -0
- data/spec/finders/data_mapper_test_connector.rb +54 -0
- data/spec/finders/sequel_spec.rb +67 -0
- data/spec/finders/sequel_test_connector.rb +9 -0
- data/spec/fixtures/admin.rb +3 -0
- data/spec/fixtures/developer.rb +13 -0
- data/spec/fixtures/developers_projects.yml +13 -0
- data/spec/fixtures/project.rb +15 -0
- data/spec/fixtures/projects.yml +6 -0
- data/spec/fixtures/replies.yml +29 -0
- data/spec/fixtures/reply.rb +9 -0
- data/spec/fixtures/schema.rb +38 -0
- data/spec/fixtures/topic.rb +7 -0
- data/spec/fixtures/topics.yml +30 -0
- data/spec/fixtures/user.rb +2 -0
- data/spec/fixtures/users.yml +35 -0
- data/spec/page_number_spec.rb +65 -0
- data/spec/per_page_spec.rb +41 -0
- data/spec/spec_helper.rb +71 -0
- data/spec/view_helpers/action_view_spec.rb +423 -0
- data/spec/view_helpers/base_spec.rb +130 -0
- data/spec/view_helpers/link_renderer_base_spec.rb +87 -0
- data/spec/view_helpers/view_example_group.rb +114 -0
- metadata +104 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
|
3
|
+
create_table "users", :force => true do |t|
|
4
|
+
t.column "name", :text
|
5
|
+
t.column "salary", :integer, :default => 70000
|
6
|
+
t.column "created_at", :datetime
|
7
|
+
t.column "updated_at", :datetime
|
8
|
+
t.column "type", :text
|
9
|
+
end
|
10
|
+
|
11
|
+
create_table "projects", :force => true do |t|
|
12
|
+
t.column "name", :text
|
13
|
+
end
|
14
|
+
|
15
|
+
create_table "developers_projects", :id => false, :force => true do |t|
|
16
|
+
t.column "developer_id", :integer, :null => false
|
17
|
+
t.column "project_id", :integer, :null => false
|
18
|
+
t.column "joined_on", :date
|
19
|
+
t.column "access_level", :integer, :default => 1
|
20
|
+
end
|
21
|
+
|
22
|
+
create_table "topics", :force => true do |t|
|
23
|
+
t.column "project_id", :integer
|
24
|
+
t.column "title", :string
|
25
|
+
t.column "subtitle", :string
|
26
|
+
t.column "content", :text
|
27
|
+
t.column "created_at", :datetime
|
28
|
+
t.column "updated_at", :datetime
|
29
|
+
end
|
30
|
+
|
31
|
+
create_table "replies", :force => true do |t|
|
32
|
+
t.column "content", :text
|
33
|
+
t.column "created_at", :datetime
|
34
|
+
t.column "updated_at", :datetime
|
35
|
+
t.column "topic_id", :integer
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
class Topic < ActiveRecord::Base
|
2
|
+
has_many :replies, :dependent => :destroy, :order => 'replies.created_at DESC'
|
3
|
+
belongs_to :project
|
4
|
+
|
5
|
+
scope :mentions_activerecord, :conditions => ['topics.title LIKE ?', '%ActiveRecord%']
|
6
|
+
scope :distinct, :select => "DISTINCT #{table_name}.*"
|
7
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
futurama:
|
2
|
+
id: 1
|
3
|
+
title: Isnt futurama awesome?
|
4
|
+
subtitle: It really is, isnt it.
|
5
|
+
content: I like futurama
|
6
|
+
created_at: <%= 1.day.ago.utc.to_s(:db) %>
|
7
|
+
updated_at:
|
8
|
+
|
9
|
+
harvey_birdman:
|
10
|
+
id: 2
|
11
|
+
title: Harvey Birdman is the king of all men
|
12
|
+
subtitle: yup
|
13
|
+
content: He really is
|
14
|
+
created_at: <%= 2.hours.ago.utc.to_s(:db) %>
|
15
|
+
updated_at:
|
16
|
+
|
17
|
+
rails:
|
18
|
+
id: 3
|
19
|
+
project_id: 1
|
20
|
+
title: Rails is nice
|
21
|
+
subtitle: It makes me happy
|
22
|
+
content: except when I have to hack internals to fix pagination. even then really.
|
23
|
+
created_at: <%= 20.minutes.ago.utc.to_s(:db) %>
|
24
|
+
|
25
|
+
ar:
|
26
|
+
id: 4
|
27
|
+
project_id: 1
|
28
|
+
title: ActiveRecord sometimes freaks me out
|
29
|
+
content: "I mean, what's the deal with eager loading?"
|
30
|
+
created_at: <%= 15.minutes.ago.utc.to_s(:db) %>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
david:
|
2
|
+
id: 1
|
3
|
+
name: David
|
4
|
+
salary: 80000
|
5
|
+
type: Developer
|
6
|
+
|
7
|
+
jamis:
|
8
|
+
id: 2
|
9
|
+
name: Jamis
|
10
|
+
salary: 150000
|
11
|
+
type: Developer
|
12
|
+
|
13
|
+
<% for digit in 3..10 %>
|
14
|
+
dev_<%= digit %>:
|
15
|
+
id: <%= digit %>
|
16
|
+
name: fixture_<%= digit %>
|
17
|
+
salary: 100000
|
18
|
+
type: Developer
|
19
|
+
<% end %>
|
20
|
+
|
21
|
+
poor_jamis:
|
22
|
+
id: 11
|
23
|
+
name: Jamis
|
24
|
+
salary: 9000
|
25
|
+
type: Developer
|
26
|
+
|
27
|
+
admin:
|
28
|
+
id: 12
|
29
|
+
name: admin
|
30
|
+
type: Admin
|
31
|
+
|
32
|
+
goofy:
|
33
|
+
id: 13
|
34
|
+
name: Goofy
|
35
|
+
type: Admin
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'will_paginate/page_number'
|
3
|
+
|
4
|
+
describe WillPaginate::PageNumber do
|
5
|
+
describe "valid" do
|
6
|
+
subject { described_class.new('12', 'page') }
|
7
|
+
|
8
|
+
it { should eq(12) }
|
9
|
+
its(:inspect) { should eq('page 12') }
|
10
|
+
it { should be_a(WillPaginate::PageNumber) }
|
11
|
+
it { should be_instance_of(WillPaginate::PageNumber) }
|
12
|
+
it { should be_a(Numeric) }
|
13
|
+
it { should be_a(Fixnum) }
|
14
|
+
it { should_not be_instance_of(Fixnum) }
|
15
|
+
|
16
|
+
it "passes the PageNumber=== type check" do |variable|
|
17
|
+
(WillPaginate::PageNumber === subject).should be
|
18
|
+
end
|
19
|
+
|
20
|
+
it "passes the Numeric=== type check" do |variable|
|
21
|
+
(Numeric === subject).should be
|
22
|
+
(Fixnum === subject).should be
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "invalid" do
|
27
|
+
def create(value, name = 'page')
|
28
|
+
described_class.new(value, name)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "errors out on non-int values" do
|
32
|
+
lambda { create(nil) }.should raise_error(WillPaginate::InvalidPage)
|
33
|
+
lambda { create('') }.should raise_error(WillPaginate::InvalidPage)
|
34
|
+
lambda { create('Schnitzel') }.should raise_error(WillPaginate::InvalidPage)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "errors out on zero or less" do
|
38
|
+
lambda { create(0) }.should raise_error(WillPaginate::InvalidPage)
|
39
|
+
lambda { create(-1) }.should raise_error(WillPaginate::InvalidPage)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "doesn't error out on zero for 'offset'" do
|
43
|
+
lambda { create(0, 'offset') }.should_not raise_error
|
44
|
+
lambda { create(-1, 'offset') }.should raise_error(WillPaginate::InvalidPage)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "coercion method" do
|
49
|
+
it "defaults to 'page' name" do
|
50
|
+
num = WillPaginate::PageNumber(12)
|
51
|
+
num.inspect.should eq('page 12')
|
52
|
+
end
|
53
|
+
|
54
|
+
it "accepts a custom name" do
|
55
|
+
num = WillPaginate::PageNumber(12, 'monkeys')
|
56
|
+
num.inspect.should eq('monkeys 12')
|
57
|
+
end
|
58
|
+
|
59
|
+
it "doesn't affect PageNumber instances" do
|
60
|
+
num = WillPaginate::PageNumber(12)
|
61
|
+
num2 = WillPaginate::PageNumber(num)
|
62
|
+
num2.object_id.should eq(num.object_id)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'will_paginate/per_page'
|
3
|
+
|
4
|
+
describe WillPaginate::PerPage do
|
5
|
+
|
6
|
+
class MyModel
|
7
|
+
extend WillPaginate::PerPage
|
8
|
+
end
|
9
|
+
|
10
|
+
it "has the default value" do
|
11
|
+
MyModel.per_page.should == 30
|
12
|
+
|
13
|
+
WillPaginate.per_page = 10
|
14
|
+
begin
|
15
|
+
MyModel.per_page.should == 10
|
16
|
+
ensure
|
17
|
+
WillPaginate.per_page = 30
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "casts values to int" do
|
22
|
+
WillPaginate.per_page = '10'
|
23
|
+
begin
|
24
|
+
MyModel.per_page.should == 10
|
25
|
+
ensure
|
26
|
+
WillPaginate.per_page = 30
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it "has an explicit value" do
|
31
|
+
MyModel.per_page = 12
|
32
|
+
begin
|
33
|
+
MyModel.per_page.should == 12
|
34
|
+
subclass = Class.new(MyModel)
|
35
|
+
subclass.per_page.should == 12
|
36
|
+
ensure
|
37
|
+
MyModel.send(:remove_instance_variable, '@per_page')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require File.expand_path('../view_helpers/view_example_group', __FILE__)
|
3
|
+
begin
|
4
|
+
require 'ruby-debug'
|
5
|
+
rescue LoadError
|
6
|
+
# no debugger available
|
7
|
+
end
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
config.include Module.new {
|
11
|
+
protected
|
12
|
+
|
13
|
+
def include_phrase(string)
|
14
|
+
PhraseMatcher.new(string)
|
15
|
+
end
|
16
|
+
|
17
|
+
def have_deprecation(msg)
|
18
|
+
DeprecationMatcher.new(msg)
|
19
|
+
end
|
20
|
+
}
|
21
|
+
|
22
|
+
config.mock_with :mocha
|
23
|
+
end
|
24
|
+
|
25
|
+
class PhraseMatcher
|
26
|
+
def initialize(string)
|
27
|
+
@string = string
|
28
|
+
@pattern = /\b#{Regexp.escape string}\b/
|
29
|
+
end
|
30
|
+
|
31
|
+
def matches?(actual)
|
32
|
+
@actual = actual.to_s
|
33
|
+
@actual =~ @pattern
|
34
|
+
end
|
35
|
+
|
36
|
+
def failure_message
|
37
|
+
"expected #{@actual.inspect} to contain phrase #{@string.inspect}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def negative_failure_message
|
41
|
+
"expected #{@actual.inspect} not to contain phrase #{@string.inspect}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
require 'stringio'
|
46
|
+
|
47
|
+
class DeprecationMatcher
|
48
|
+
def initialize(message)
|
49
|
+
@message = message
|
50
|
+
end
|
51
|
+
|
52
|
+
def matches?(block)
|
53
|
+
@actual = hijack_stderr(&block)
|
54
|
+
PhraseMatcher.new("DEPRECATION WARNING: #{@message}").matches?(@actual)
|
55
|
+
end
|
56
|
+
|
57
|
+
def failure_message
|
58
|
+
"expected deprecation warning #{@message.inspect}, got #{@actual.inspect}"
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def hijack_stderr
|
64
|
+
err = $stderr
|
65
|
+
$stderr = StringIO.new
|
66
|
+
yield
|
67
|
+
$stderr.string.rstrip
|
68
|
+
ensure
|
69
|
+
$stderr = err
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,423 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_support/rescuable' # needed for Ruby 1.9.1
|
3
|
+
require 'action_controller'
|
4
|
+
require 'will_paginate/view_helpers/action_view'
|
5
|
+
require 'will_paginate/collection'
|
6
|
+
|
7
|
+
Routes = ActionDispatch::Routing::RouteSet.new
|
8
|
+
|
9
|
+
Routes.draw do
|
10
|
+
match 'dummy/page/:page' => 'dummy#index'
|
11
|
+
match 'dummy/dots/page.:page' => 'dummy#dots'
|
12
|
+
match 'ibocorp(/:page)' => 'ibocorp#index',
|
13
|
+
:constraints => { :page => /\d+/ }, :defaults => { :page => 1 }
|
14
|
+
|
15
|
+
match ':controller(/:action(/:id(.:format)))'
|
16
|
+
end
|
17
|
+
|
18
|
+
describe WillPaginate::ActionView do
|
19
|
+
|
20
|
+
before(:all) do
|
21
|
+
I18n.load_path.concat WillPaginate::I18n.load_path
|
22
|
+
end
|
23
|
+
|
24
|
+
before(:each) do
|
25
|
+
I18n.reload!
|
26
|
+
end
|
27
|
+
|
28
|
+
before(:each) do
|
29
|
+
@assigns = {}
|
30
|
+
@controller = DummyController.new
|
31
|
+
@request = @controller.request
|
32
|
+
@template = '<%= will_paginate collection, options %>'
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_reader :assigns, :controller, :request
|
36
|
+
|
37
|
+
def render(locals)
|
38
|
+
@view = ActionView::Base.new([], @assigns, @controller)
|
39
|
+
@view.request = @request
|
40
|
+
@view.singleton_class.send(:include, @controller._routes.url_helpers)
|
41
|
+
@view.render(:inline => @template, :locals => locals)
|
42
|
+
end
|
43
|
+
|
44
|
+
## basic pagination ##
|
45
|
+
|
46
|
+
it "should render" do
|
47
|
+
paginate do |pagination|
|
48
|
+
assert_select 'a[href]', 3 do |elements|
|
49
|
+
validate_page_numbers [2,3,2], elements
|
50
|
+
assert_select elements.last, ':last-child', "Next →"
|
51
|
+
end
|
52
|
+
assert_select 'span', 1
|
53
|
+
assert_select 'span.disabled:first-child', '← Previous'
|
54
|
+
assert_select 'em.current', '1'
|
55
|
+
pagination.first.inner_text.should == '← Previous 1 2 3 Next →'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should render nothing when there is only 1 page" do
|
60
|
+
paginate(:per_page => 30).should be_empty
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should paginate with options" do
|
64
|
+
paginate({ :page => 2 }, :class => 'will_paginate', :previous_label => 'Prev', :next_label => 'Next') do
|
65
|
+
assert_select 'a[href]', 4 do |elements|
|
66
|
+
validate_page_numbers [1,1,3,3], elements
|
67
|
+
# test rel attribute values:
|
68
|
+
assert_select elements[1], 'a', '1' do |link|
|
69
|
+
link.first['rel'].should == 'prev start'
|
70
|
+
end
|
71
|
+
assert_select elements.first, 'a', "Prev" do |link|
|
72
|
+
link.first['rel'].should == 'prev start'
|
73
|
+
end
|
74
|
+
assert_select elements.last, 'a', "Next" do |link|
|
75
|
+
link.first['rel'].should == 'next'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
assert_select '.current', '2'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should paginate using a custom renderer class" do
|
83
|
+
paginate({}, :renderer => AdditionalLinkAttributesRenderer) do
|
84
|
+
assert_select 'a[default=true]', 3
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should paginate using a custom renderer instance" do
|
89
|
+
renderer = WillPaginate::ActionView::LinkRenderer.new
|
90
|
+
def renderer.gap() '<span class="my-gap">~~</span>' end
|
91
|
+
|
92
|
+
paginate({ :per_page => 2 }, :inner_window => 0, :outer_window => 0, :renderer => renderer) do
|
93
|
+
assert_select 'span.my-gap', '~~'
|
94
|
+
end
|
95
|
+
|
96
|
+
renderer = AdditionalLinkAttributesRenderer.new(:title => 'rendered')
|
97
|
+
paginate({}, :renderer => renderer) do
|
98
|
+
assert_select 'a[title=rendered]', 3
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should have classnames on previous/next links" do
|
103
|
+
paginate do |pagination|
|
104
|
+
assert_select 'span.disabled.previous_page:first-child'
|
105
|
+
assert_select 'a.next_page[href]:last-child'
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should match expected markup" do
|
110
|
+
paginate
|
111
|
+
expected = <<-HTML
|
112
|
+
<div class="pagination"><span class="previous_page disabled">← Previous</span>
|
113
|
+
<em class="current">1</em>
|
114
|
+
<a href="/foo/bar?page=2" rel="next">2</a>
|
115
|
+
<a href="/foo/bar?page=3">3</a>
|
116
|
+
<a href="/foo/bar?page=2" class="next_page" rel="next">Next →</a></div>
|
117
|
+
HTML
|
118
|
+
expected.strip!.gsub!(/\s{2,}/, ' ')
|
119
|
+
expected_dom = HTML::Document.new(expected).root
|
120
|
+
|
121
|
+
html_document.root.should == expected_dom
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should output escaped URLs" do
|
125
|
+
paginate({:page => 1, :per_page => 1, :total_entries => 2},
|
126
|
+
:page_links => false, :params => { :tag => '<br>' })
|
127
|
+
|
128
|
+
assert_select 'a[href]', 1 do |links|
|
129
|
+
query = links.first['href'].split('?', 2)[1]
|
130
|
+
query.split('&').sort.should == %w(page=2 tag=%3Cbr%3E)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
## advanced options for pagination ##
|
135
|
+
|
136
|
+
it "should be able to render without container" do
|
137
|
+
paginate({}, :container => false)
|
138
|
+
assert_select 'div.pagination', 0, 'main DIV present when it shouldn\'t'
|
139
|
+
assert_select 'a[href]', 3
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should be able to render without page links" do
|
143
|
+
paginate({ :page => 2 }, :page_links => false) do
|
144
|
+
assert_select 'a[href]', 2 do |elements|
|
145
|
+
validate_page_numbers [1,3], elements
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
## other helpers ##
|
151
|
+
|
152
|
+
it "should render a paginated section" do
|
153
|
+
@template = <<-ERB
|
154
|
+
<%= paginated_section collection, options do %>
|
155
|
+
<%= content_tag :div, '', :id => "developers" %>
|
156
|
+
<% end %>
|
157
|
+
ERB
|
158
|
+
|
159
|
+
paginate
|
160
|
+
assert_select 'div.pagination', 2
|
161
|
+
assert_select 'div.pagination + div#developers', 1
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should not render a paginated section with a single page" do
|
165
|
+
@template = <<-ERB
|
166
|
+
<%= paginated_section collection, options do %>
|
167
|
+
<%= content_tag :div, '', :id => "developers" %>
|
168
|
+
<% end %>
|
169
|
+
ERB
|
170
|
+
|
171
|
+
paginate(:total_entries => 1)
|
172
|
+
assert_select 'div.pagination', 0
|
173
|
+
assert_select 'div#developers', 1
|
174
|
+
end
|
175
|
+
|
176
|
+
## parameter handling in page links ##
|
177
|
+
|
178
|
+
it "should preserve parameters on GET" do
|
179
|
+
request.params :foo => { :bar => 'baz' }
|
180
|
+
paginate
|
181
|
+
assert_links_match /foo\[bar\]=baz/
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should not preserve parameters on POST" do
|
185
|
+
request.post
|
186
|
+
request.params :foo => 'bar'
|
187
|
+
paginate
|
188
|
+
assert_no_links_match /foo=bar/
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should add additional parameters to links" do
|
192
|
+
paginate({}, :params => { :foo => 'bar' })
|
193
|
+
assert_links_match /foo=bar/
|
194
|
+
end
|
195
|
+
|
196
|
+
it "should add anchor parameter" do
|
197
|
+
paginate({}, :params => { :anchor => 'anchor' })
|
198
|
+
assert_links_match /#anchor$/
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should remove arbitrary parameters" do
|
202
|
+
request.params :foo => 'bar'
|
203
|
+
paginate({}, :params => { :foo => nil })
|
204
|
+
assert_no_links_match /foo=bar/
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should override default route parameters" do
|
208
|
+
paginate({}, :params => { :controller => 'baz', :action => 'list' })
|
209
|
+
assert_links_match %r{\Wbaz/list\W}
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should paginate with custom page parameter" do
|
213
|
+
paginate({ :page => 2 }, :param_name => :developers_page) do
|
214
|
+
assert_select 'a[href]', 4 do |elements|
|
215
|
+
validate_page_numbers [1,1,3,3], elements, :developers_page
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
it "should paginate with complex custom page parameter" do
|
221
|
+
request.params :developers => { :page => 2 }
|
222
|
+
|
223
|
+
paginate({ :page => 2 }, :param_name => 'developers[page]') do
|
224
|
+
assert_select 'a[href]', 4 do |links|
|
225
|
+
assert_links_match /\?developers\[page\]=\d+$/, links
|
226
|
+
validate_page_numbers [1,1,3,3], links, 'developers[page]'
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should paginate with custom route page parameter" do
|
232
|
+
request.symbolized_path_parameters.update :controller => 'dummy', :action => nil
|
233
|
+
paginate :per_page => 2 do
|
234
|
+
assert_select 'a[href]', 6 do |links|
|
235
|
+
assert_links_match %r{/page/(\d+)$}, links, [2, 3, 4, 5, 6, 2]
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
it "should paginate with custom route with dot separator page parameter" do
|
241
|
+
request.symbolized_path_parameters.update :controller => 'dummy', :action => 'dots'
|
242
|
+
paginate :per_page => 2 do
|
243
|
+
assert_select 'a[href]', 6 do |links|
|
244
|
+
assert_links_match %r{/page\.(\d+)$}, links, [2, 3, 4, 5, 6, 2]
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
it "should paginate with custom route and first page number implicit" do
|
250
|
+
request.symbolized_path_parameters.update :controller => 'ibocorp', :action => nil
|
251
|
+
paginate :page => 2, :per_page => 2 do
|
252
|
+
assert_select 'a[href]', 7 do |links|
|
253
|
+
assert_links_match %r{/ibocorp(?:/(\d+))?$}, links, [nil, nil, 3, 4, 5, 6, 3]
|
254
|
+
end
|
255
|
+
end
|
256
|
+
# Routes.recognize_path('/ibocorp/2').should == {:page=>'2', :action=>'index', :controller=>'ibocorp'}
|
257
|
+
# Routes.recognize_path('/ibocorp/foo').should == {:action=>'foo', :controller=>'ibocorp'}
|
258
|
+
end
|
259
|
+
|
260
|
+
## internal hardcore stuff ##
|
261
|
+
|
262
|
+
it "should be able to guess the collection name" do
|
263
|
+
collection = mock
|
264
|
+
collection.expects(:total_pages).returns(1)
|
265
|
+
|
266
|
+
@template = '<%= will_paginate options %>'
|
267
|
+
controller.controller_name = 'developers'
|
268
|
+
assigns['developers'] = collection
|
269
|
+
|
270
|
+
paginate(nil)
|
271
|
+
end
|
272
|
+
|
273
|
+
it "should fail if the inferred collection is nil" do
|
274
|
+
@template = '<%= will_paginate options %>'
|
275
|
+
controller.controller_name = 'developers'
|
276
|
+
|
277
|
+
lambda {
|
278
|
+
paginate(nil)
|
279
|
+
}.should raise_error(ActionView::TemplateError, /@developers/)
|
280
|
+
end
|
281
|
+
|
282
|
+
## i18n
|
283
|
+
|
284
|
+
it "is able to translate previous/next labels" do
|
285
|
+
translation :will_paginate => {
|
286
|
+
:previous_label => 'Go back',
|
287
|
+
:next_label => 'Load more'
|
288
|
+
}
|
289
|
+
|
290
|
+
paginate do |pagination|
|
291
|
+
assert_select 'span.disabled:first-child', 'Go back'
|
292
|
+
assert_select 'a[rel=next]', 'Load more'
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
it "renders using ActionView helpers on a custom object" do
|
297
|
+
helper = Object.new
|
298
|
+
class << helper
|
299
|
+
attr_reader :controller
|
300
|
+
include ActionView::Helpers::UrlHelper
|
301
|
+
include Routes.url_helpers
|
302
|
+
include WillPaginate::ActionView
|
303
|
+
end
|
304
|
+
helper.default_url_options[:controller] = 'dummy'
|
305
|
+
|
306
|
+
collection = WillPaginate::Collection.new(2, 1, 3)
|
307
|
+
@render_output = helper.will_paginate(collection)
|
308
|
+
|
309
|
+
assert_select 'a[href]', 4 do |links|
|
310
|
+
urls = links.map {|l| l['href'] }.uniq
|
311
|
+
urls.should == ['/dummy/page/1', '/dummy/page/3']
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
it "renders using ActionDispatch helper on a custom object" do
|
316
|
+
helper = Object.new
|
317
|
+
class << helper
|
318
|
+
include ActionDispatch::Routing::UrlFor
|
319
|
+
include Routes.url_helpers
|
320
|
+
include WillPaginate::ActionView
|
321
|
+
end
|
322
|
+
helper.default_url_options[:host] = 'example.com'
|
323
|
+
helper.default_url_options[:controller] = 'dummy'
|
324
|
+
# helper.default_url_options[:only_path] = true
|
325
|
+
|
326
|
+
collection = WillPaginate::Collection.new(2, 1, 3)
|
327
|
+
@render_output = helper.will_paginate(collection)
|
328
|
+
|
329
|
+
assert_select 'a[href]', 4 do |links|
|
330
|
+
urls = links.map {|l| l['href'] }.uniq
|
331
|
+
urls.should == ['http://example.com/dummy/page/1', 'http://example.com/dummy/page/3']
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
private
|
336
|
+
|
337
|
+
def translation(data)
|
338
|
+
I18n.available_locales # triggers loading existing translations
|
339
|
+
I18n.backend.store_translations(:en, data)
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
class AdditionalLinkAttributesRenderer < WillPaginate::ActionView::LinkRenderer
|
344
|
+
def initialize(link_attributes = nil)
|
345
|
+
super()
|
346
|
+
@additional_link_attributes = link_attributes || { :default => 'true' }
|
347
|
+
end
|
348
|
+
|
349
|
+
def link(text, target, attributes = {})
|
350
|
+
super(text, target, attributes.merge(@additional_link_attributes))
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
class DummyController
|
355
|
+
attr_reader :request
|
356
|
+
attr_accessor :controller_name
|
357
|
+
|
358
|
+
include ActionController::UrlFor
|
359
|
+
include Routes.url_helpers
|
360
|
+
|
361
|
+
def initialize
|
362
|
+
@request = DummyRequest.new
|
363
|
+
end
|
364
|
+
|
365
|
+
def params
|
366
|
+
@request.params
|
367
|
+
end
|
368
|
+
|
369
|
+
def env
|
370
|
+
{}
|
371
|
+
end
|
372
|
+
|
373
|
+
def _prefixes
|
374
|
+
[]
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
class IbocorpController < DummyController
|
379
|
+
end
|
380
|
+
|
381
|
+
class DummyRequest
|
382
|
+
attr_accessor :symbolized_path_parameters
|
383
|
+
|
384
|
+
def initialize
|
385
|
+
@get = true
|
386
|
+
@params = {}
|
387
|
+
@symbolized_path_parameters = { :controller => 'foo', :action => 'bar' }
|
388
|
+
end
|
389
|
+
|
390
|
+
def get?
|
391
|
+
@get
|
392
|
+
end
|
393
|
+
|
394
|
+
def post
|
395
|
+
@get = false
|
396
|
+
end
|
397
|
+
|
398
|
+
def relative_url_root
|
399
|
+
''
|
400
|
+
end
|
401
|
+
|
402
|
+
def script_name
|
403
|
+
''
|
404
|
+
end
|
405
|
+
|
406
|
+
def params(more = nil)
|
407
|
+
@params.update(more) if more
|
408
|
+
@params
|
409
|
+
end
|
410
|
+
|
411
|
+
def host_with_port
|
412
|
+
'example.com'
|
413
|
+
end
|
414
|
+
alias host host_with_port
|
415
|
+
|
416
|
+
def optional_port
|
417
|
+
''
|
418
|
+
end
|
419
|
+
|
420
|
+
def protocol
|
421
|
+
'http:'
|
422
|
+
end
|
423
|
+
end
|