merb_paginate 0.9.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.
- data/CHANGELOG.rdoc +105 -0
- data/LICENSE +18 -0
- data/README.rdoc +125 -0
- data/Rakefile +59 -0
- data/lib/merbtasks.rb +17 -0
- data/lib/will_paginate.rb +40 -0
- data/lib/will_paginate/array.rb +35 -0
- data/lib/will_paginate/collection.rb +145 -0
- data/lib/will_paginate/core_ext.rb +58 -0
- data/lib/will_paginate/deprecation.rb +50 -0
- data/lib/will_paginate/finders.rb +9 -0
- data/lib/will_paginate/finders/active_record.rb +192 -0
- data/lib/will_paginate/finders/active_record/named_scope.rb +170 -0
- data/lib/will_paginate/finders/active_record/named_scope_patch.rb +39 -0
- data/lib/will_paginate/finders/active_resource.rb +51 -0
- data/lib/will_paginate/finders/base.rb +112 -0
- data/lib/will_paginate/finders/data_mapper.rb +30 -0
- data/lib/will_paginate/finders/sequel.rb +21 -0
- data/lib/will_paginate/version.rb +9 -0
- data/lib/will_paginate/view_helpers.rb +42 -0
- data/lib/will_paginate/view_helpers/base.rb +126 -0
- data/lib/will_paginate/view_helpers/link_renderer.rb +130 -0
- data/lib/will_paginate/view_helpers/link_renderer_base.rb +83 -0
- data/lib/will_paginate/view_helpers/merb.rb +13 -0
- data/spec/collection_spec.rb +147 -0
- data/spec/console +8 -0
- data/spec/console_fixtures.rb +8 -0
- data/spec/database.yml +22 -0
- data/spec/finders/active_record_spec.rb +461 -0
- data/spec/finders/active_resource_spec.rb +52 -0
- data/spec/finders/activerecord_test_connector.rb +108 -0
- data/spec/finders/data_mapper_spec.rb +62 -0
- data/spec/finders/data_mapper_test_connector.rb +20 -0
- data/spec/finders/sequel_spec.rb +53 -0
- data/spec/finders/sequel_test_connector.rb +9 -0
- data/spec/finders_spec.rb +76 -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 +7 -0
- data/spec/fixtures/schema.rb +38 -0
- data/spec/fixtures/topic.rb +6 -0
- data/spec/fixtures/topics.yml +30 -0
- data/spec/fixtures/user.rb +2 -0
- data/spec/fixtures/users.yml +35 -0
- data/spec/rcov.opts +2 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +75 -0
- data/spec/tasks.rake +60 -0
- data/spec/view_helpers/base_spec.rb +64 -0
- data/spec/view_helpers/link_renderer_base_spec.rb +84 -0
- data/spec/view_helpers/view_example_group.rb +111 -0
- metadata +126 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
witty_retort:
|
2
|
+
id: 1
|
3
|
+
topic_id: 1
|
4
|
+
content: Birdman is better!
|
5
|
+
created_at: <%= 6.hours.ago.to_s(:db) %>
|
6
|
+
|
7
|
+
another:
|
8
|
+
id: 2
|
9
|
+
topic_id: 2
|
10
|
+
content: Nuh uh!
|
11
|
+
created_at: <%= 1.hour.ago.to_s(:db) %>
|
12
|
+
|
13
|
+
spam:
|
14
|
+
id: 3
|
15
|
+
topic_id: 1
|
16
|
+
content: Nice site!
|
17
|
+
created_at: <%= 1.hour.ago.to_s(:db) %>
|
18
|
+
|
19
|
+
decisive:
|
20
|
+
id: 4
|
21
|
+
topic_id: 4
|
22
|
+
content: "I'm getting to the bottom of this"
|
23
|
+
created_at: <%= 30.minutes.ago.to_s(:db) %>
|
24
|
+
|
25
|
+
brave:
|
26
|
+
id: 5
|
27
|
+
topic_id: 4
|
28
|
+
content: "AR doesn't scare me a bit"
|
29
|
+
created_at: <%= 10.minutes.ago.to_s(:db) %>
|
@@ -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,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.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.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.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.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
|
data/spec/rcov.opts
ADDED
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
|
4
|
+
module MyExtras
|
5
|
+
protected
|
6
|
+
|
7
|
+
def include_phrase(string)
|
8
|
+
PhraseMatcher.new(string)
|
9
|
+
end
|
10
|
+
|
11
|
+
def collection(params = {})
|
12
|
+
if params[:total_pages]
|
13
|
+
params[:per_page] = 1
|
14
|
+
params[:total_entries] = params[:total_pages]
|
15
|
+
end
|
16
|
+
WillPaginate::Collection.new(params[:page] || 1, params[:per_page] || 30, params[:total_entries])
|
17
|
+
end
|
18
|
+
|
19
|
+
def have_deprecation
|
20
|
+
DeprecationMatcher.new
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
Spec::Runner.configure do |config|
|
25
|
+
# config.include My::Pony, My::Horse, :type => :farm
|
26
|
+
config.include MyExtras
|
27
|
+
# config.predicate_matchers[:swim] = :can_swim?
|
28
|
+
|
29
|
+
config.mock_with :mocha
|
30
|
+
end
|
31
|
+
|
32
|
+
class PhraseMatcher
|
33
|
+
def initialize(string)
|
34
|
+
@string = string
|
35
|
+
@pattern = /\b#{string}\b/
|
36
|
+
end
|
37
|
+
|
38
|
+
def matches?(actual)
|
39
|
+
@actual = actual.to_s
|
40
|
+
@actual =~ @pattern
|
41
|
+
end
|
42
|
+
|
43
|
+
def failure_message
|
44
|
+
"expected #{@actual.inspect} to contain phrase #{@string.inspect}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def negative_failure_message
|
48
|
+
"expected #{@actual.inspect} not to contain phrase #{@string.inspect}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class DeprecationMatcher
|
53
|
+
def initialize
|
54
|
+
@old_behavior = WillPaginate::Deprecation.behavior
|
55
|
+
@messages = []
|
56
|
+
WillPaginate::Deprecation.behavior = lambda { |message, callstack|
|
57
|
+
@messages << message
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def matches?(block)
|
62
|
+
block.call
|
63
|
+
!@messages.empty?
|
64
|
+
ensure
|
65
|
+
WillPaginate::Deprecation.behavior = @old_behavior
|
66
|
+
end
|
67
|
+
|
68
|
+
def failure_message
|
69
|
+
"expected block to raise a deprecation warning"
|
70
|
+
end
|
71
|
+
|
72
|
+
def negative_failure_message
|
73
|
+
"expected block not to raise deprecation warnings, #{@messages.size} raised"
|
74
|
+
end
|
75
|
+
end
|
data/spec/tasks.rake
ADDED
@@ -0,0 +1,60 @@
|
|
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 << 'lib' << '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'
|
16
|
+
Spec::Rake::SpecTask.new(:rails) do |t|
|
17
|
+
t.libs << 'lib' << '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 << 'lib' << '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 << 'lib' << '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 << 'lib' << '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 << 'lib' << '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 << 'lib' << 'spec'
|
57
|
+
t.spec_opts = ['--format', 'html:doc/spec_results.html', '--diff']
|
58
|
+
t.fail_on_error = false
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'will_paginate/view_helpers/base'
|
3
|
+
require 'will_paginate/array'
|
4
|
+
|
5
|
+
describe WillPaginate::ViewHelpers::Base do
|
6
|
+
|
7
|
+
include WillPaginate::ViewHelpers::Base
|
8
|
+
|
9
|
+
describe "will_paginate" do
|
10
|
+
it "should render" do
|
11
|
+
collection = WillPaginate::Collection.new(1, 2, 4)
|
12
|
+
renderer = mock 'Renderer'
|
13
|
+
renderer.expects(:prepare).with(collection, instance_of(Hash), self)
|
14
|
+
renderer.expects(:to_html).returns('<PAGES>')
|
15
|
+
|
16
|
+
will_paginate(collection, :renderer => renderer).should == '<PAGES>'
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return nil for single-page collections" do
|
20
|
+
collection = mock 'Collection', :total_pages => 1
|
21
|
+
will_paginate(collection).should be_nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "page_entries_info" do
|
26
|
+
before :all do
|
27
|
+
@array = ('a'..'z').to_a
|
28
|
+
end
|
29
|
+
|
30
|
+
def info(params, options = {})
|
31
|
+
options[:html] ||= false unless options.key?(:html) and options[:html].nil?
|
32
|
+
collection = Hash === params ? @array.paginate(params) : params
|
33
|
+
page_entries_info collection, options
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should display middle results and total count" do
|
37
|
+
info(:page => 2, :per_page => 5).should == "Displaying strings 6 - 10 of 26 in total"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should output HTML by default" do
|
41
|
+
info({ :page => 2, :per_page => 5 }, :html => nil).should ==
|
42
|
+
"Displaying strings <b>6 - 10</b> of <b>26</b> in total"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should display shortened end results" do
|
46
|
+
info(:page => 7, :per_page => 4).should include_phrase('strings 25 - 26')
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should handle longer class names" do
|
50
|
+
collection = @array.paginate(:page => 2, :per_page => 5)
|
51
|
+
collection.first.stubs(:class).returns(mock('Class', :name => 'ProjectType'))
|
52
|
+
info(collection).should include_phrase('project types')
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should adjust output for single-page collections" do
|
56
|
+
info(('a'..'d').to_a.paginate(:page => 1, :per_page => 5)).should == "Displaying all 4 strings"
|
57
|
+
info(['a'].paginate(:page => 1, :per_page => 5)).should == "Displaying 1 string"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should display 'no entries found' for empty collections" do
|
61
|
+
info([].paginate(:page => 1, :per_page => 5)).should == "No entries found"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'will_paginate/view_helpers/link_renderer_base'
|
3
|
+
require 'will_paginate/collection'
|
4
|
+
|
5
|
+
describe WillPaginate::ViewHelpers::LinkRendererBase do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@renderer = WillPaginate::ViewHelpers::LinkRendererBase.new
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should raise error when unprepared" do
|
12
|
+
lambda {
|
13
|
+
@renderer.send :param_name
|
14
|
+
}.should raise_error
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should prepare with collection and options" do
|
18
|
+
prepare({}, :param_name => 'mypage')
|
19
|
+
@renderer.send(:current_page).should == 1
|
20
|
+
@renderer.send(:param_name).should == 'mypage'
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should have total_pages accessor" do
|
24
|
+
prepare :total_pages => 42
|
25
|
+
lambda {
|
26
|
+
@renderer.send(:total_pages).should == 42
|
27
|
+
}.should_not have_deprecation
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should clear old cached values when prepared" do
|
31
|
+
prepare({ :total_pages => 1 }, :param_name => 'foo')
|
32
|
+
@renderer.send(:total_pages).should == 1
|
33
|
+
@renderer.send(:param_name).should == 'foo'
|
34
|
+
# prepare with different object and options:
|
35
|
+
prepare({ :total_pages => 2 }, :param_name => 'bar')
|
36
|
+
@renderer.send(:total_pages).should == 2
|
37
|
+
@renderer.send(:param_name).should == 'bar'
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should have pagination definition" do
|
41
|
+
prepare({ :total_pages => 1 }, :page_links => true)
|
42
|
+
@renderer.pagination.should == [:previous_page, 1, :next_page]
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "visible page numbers" do
|
46
|
+
it "should calculate windowed visible links" do
|
47
|
+
prepare({ :page => 6, :total_pages => 11 }, :inner_window => 1, :outer_window => 1)
|
48
|
+
showing_pages 1, 2, :gap, 5, 6, 7, :gap, 10, 11
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should eliminate small gaps" do
|
52
|
+
prepare({ :page => 6, :total_pages => 11 }, :inner_window => 2, :outer_window => 1)
|
53
|
+
# pages 4 and 8 appear instead of the gap
|
54
|
+
showing_pages 1..11
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should support having no windows at all" do
|
58
|
+
prepare({ :page => 4, :total_pages => 7 }, :inner_window => 0, :outer_window => 0)
|
59
|
+
showing_pages 1, :gap, 4, :gap, 7
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should adjust upper limit if lower is out of bounds" do
|
63
|
+
prepare({ :page => 1, :total_pages => 10 }, :inner_window => 2, :outer_window => 1)
|
64
|
+
showing_pages 1, 2, 3, 4, 5, :gap, 9, 10
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should adjust lower limit if upper is out of bounds" do
|
68
|
+
prepare({ :page => 10, :total_pages => 10 }, :inner_window => 2, :outer_window => 1)
|
69
|
+
showing_pages 1, 2, :gap, 6, 7, 8, 9, 10
|
70
|
+
end
|
71
|
+
|
72
|
+
def showing_pages(*pages)
|
73
|
+
pages = pages.first.to_a if Array === pages.first or Range === pages.first
|
74
|
+
@renderer.send(:windowed_page_numbers).should == pages
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
protected
|
79
|
+
|
80
|
+
def prepare(collection_options, options = {})
|
81
|
+
@renderer.prepare(collection(collection_options), options)
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|