will_paginate-rails3 3.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +105 -0
- data/LICENSE +18 -0
- data/README.rdoc +125 -0
- data/Rakefile +32 -0
- data/lib/will_paginate.rb +23 -0
- data/lib/will_paginate/array.rb +33 -0
- data/lib/will_paginate/collection.rb +145 -0
- data/lib/will_paginate/core_ext.rb +69 -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 +158 -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 +23 -0
- data/lib/will_paginate/railtie.rb +24 -0
- data/lib/will_paginate/version.rb +9 -0
- data/lib/will_paginate/view_helpers.rb +42 -0
- data/lib/will_paginate/view_helpers/action_view.rb +134 -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 +377 -0
- data/spec/finders/active_resource_spec.rb +52 -0
- data/spec/finders/activerecord_test_connector.rb +114 -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 +13 -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 +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/rcov.opts +2 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +74 -0
- data/spec/tasks.rake +60 -0
- data/spec/view_helpers/action_view_spec.rb +356 -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 +103 -0
- metadata +127 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'will_paginate/finders/active_resource'
|
3
|
+
require 'active_resource/http_mock'
|
4
|
+
|
5
|
+
class AresProject < ActiveResource::Base
|
6
|
+
self.site = 'http://localhost:4000'
|
7
|
+
end
|
8
|
+
|
9
|
+
describe WillPaginate::Finders::ActiveResource do
|
10
|
+
|
11
|
+
before :all do
|
12
|
+
# ActiveResource::HttpMock.respond_to do |mock|
|
13
|
+
# mock.get "/ares_projects.xml?page=1&per_page=5", {}, [].to_xml
|
14
|
+
# end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should integrate with ActiveResource::Base" do
|
18
|
+
ActiveResource::Base.should respond_to(:paginate)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should error when no parameters for #paginate" do
|
22
|
+
lambda { AresProject.paginate }.should raise_error(ArgumentError)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should paginate" do
|
26
|
+
AresProject.expects(:find_every).with(:params => { :page => 1, :per_page => 5 }).returns([])
|
27
|
+
AresProject.paginate(:page => 1, :per_page => 5)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should have 30 per_page as default" do
|
31
|
+
AresProject.expects(:find_every).with(:params => { :page => 1, :per_page => 30 }).returns([])
|
32
|
+
AresProject.paginate(:page => 1)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should support #paginate(:all)" do
|
36
|
+
lambda { AresProject.paginate(:all) }.should raise_error(ArgumentError)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should error #paginate(:other)" do
|
40
|
+
lambda { AresProject.paginate(:first) }.should raise_error(ArgumentError)
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def create(page = 2, limit = 5, total = nil, &block)
|
46
|
+
if block_given?
|
47
|
+
WillPaginate::Collection.create(page, limit, total, &block)
|
48
|
+
else
|
49
|
+
WillPaginate::Collection.new(page, limit, total)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'active_record/version'
|
3
|
+
require 'active_record/fixtures'
|
4
|
+
require 'active_support/multibyte' # needed for Ruby 1.9.1
|
5
|
+
|
6
|
+
$query_count = $query_sql = nil
|
7
|
+
|
8
|
+
class ActiverecordTestConnector
|
9
|
+
cattr_accessor :able_to_connect
|
10
|
+
cattr_accessor :connected
|
11
|
+
|
12
|
+
FIXTURES_PATH = File.expand_path('../../fixtures', __FILE__)
|
13
|
+
|
14
|
+
# Set our defaults
|
15
|
+
self.connected = false
|
16
|
+
self.able_to_connect = true
|
17
|
+
|
18
|
+
def self.setup
|
19
|
+
unless self.connected || !self.able_to_connect
|
20
|
+
setup_connection
|
21
|
+
load_schema
|
22
|
+
add_load_path FIXTURES_PATH
|
23
|
+
self.connected = true
|
24
|
+
end
|
25
|
+
rescue Exception => e # errors from ActiveRecord setup
|
26
|
+
$stderr.puts "\nSkipping ActiveRecord tests: #{e}\n\n"
|
27
|
+
self.able_to_connect = false
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def self.add_load_path(path)
|
33
|
+
dep = defined?(ActiveSupport::Dependencies) ? ActiveSupport::Dependencies : ::Dependencies
|
34
|
+
dep.load_paths.unshift path
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.setup_connection
|
38
|
+
db = ENV['DB'].blank?? 'sqlite3' : ENV['DB']
|
39
|
+
|
40
|
+
configurations = YAML.load_file(File.expand_path('../../database.yml', __FILE__))
|
41
|
+
raise "no configuration for '#{db}'" unless configurations.key? db
|
42
|
+
configuration = configurations[db]
|
43
|
+
|
44
|
+
ActiveRecord::Base.logger = Logger.new(STDOUT) if $0 == 'irb'
|
45
|
+
puts "using #{configuration['adapter']} adapter"
|
46
|
+
|
47
|
+
ActiveRecord::Base.configurations = { db => configuration }
|
48
|
+
ActiveRecord::Base.establish_connection(db)
|
49
|
+
prepare ActiveRecord::Base.connection
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.load_schema
|
53
|
+
ActiveRecord::Base.silence do
|
54
|
+
ActiveRecord::Migration.verbose = false
|
55
|
+
load File.join(FIXTURES_PATH, 'schema.rb')
|
56
|
+
end
|
57
|
+
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
|
+
|
81
|
+
module FixtureSetup
|
82
|
+
def fixtures(*tables)
|
83
|
+
table_names = tables.map { |t| t.to_s }
|
84
|
+
|
85
|
+
fixtures = Fixtures.create_fixtures ActiverecordTestConnector::FIXTURES_PATH, table_names
|
86
|
+
@@loaded_fixtures = {}
|
87
|
+
@@fixture_cache = {}
|
88
|
+
|
89
|
+
unless fixtures.nil?
|
90
|
+
if fixtures.instance_of?(Fixtures)
|
91
|
+
@@loaded_fixtures[fixtures.table_name] = fixtures
|
92
|
+
else
|
93
|
+
fixtures.each { |f| @@loaded_fixtures[f.table_name] = f }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
table_names.each do |table_name|
|
98
|
+
define_method(table_name) do |*fixtures|
|
99
|
+
@@fixture_cache[table_name] ||= {}
|
100
|
+
|
101
|
+
instances = fixtures.map do |fixture|
|
102
|
+
if @@loaded_fixtures[table_name][fixture.to_s]
|
103
|
+
@@fixture_cache[table_name][fixture] ||= @@loaded_fixtures[table_name][fixture.to_s].find
|
104
|
+
else
|
105
|
+
raise StandardError, "No fixture with name '#{fixture}' found for table '#{table_name}'"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
instances.size == 1 ? instances.first : instances
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'will_paginate/finders/data_mapper'
|
3
|
+
require File.expand_path('../data_mapper_test_connector', __FILE__)
|
4
|
+
|
5
|
+
require 'will_paginate'
|
6
|
+
|
7
|
+
describe WillPaginate::Finders::DataMapper do
|
8
|
+
|
9
|
+
it "should make #paginate available to DM resource classes" do
|
10
|
+
Animal.should respond_to(:paginate)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should paginate" do
|
14
|
+
Animal.expects(:all).with(:limit => 5, :offset => 0).returns([])
|
15
|
+
Animal.paginate(:page => 1, :per_page => 5)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should NOT to paginate_by_sql" do
|
19
|
+
Animal.should_not respond_to(:paginate_by_sql)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should support explicit :all argument" do
|
23
|
+
Animal.expects(:all).with(instance_of(Hash)).returns([])
|
24
|
+
Animal.paginate(:all, :page => nil)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should support conditional pagination" do
|
28
|
+
filtered_result = Animal.paginate(:all, :name => 'Dog', :page => nil)
|
29
|
+
filtered_result.size.should == 1
|
30
|
+
filtered_result.first.should == Animal.first(:name => 'Dog')
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should leave extra parameters intact" do
|
34
|
+
Animal.expects(:all).with(:name => 'Dog', :limit => 4, :offset => 0 ).returns(Array.new(5))
|
35
|
+
Animal.expects(:count).with({:name => 'Dog'}).returns(1)
|
36
|
+
|
37
|
+
Animal.paginate :name => 'Dog', :page => 1, :per_page => 4
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "counting" do
|
41
|
+
it "should ignore nil in :count parameter" do
|
42
|
+
lambda { Animal.paginate :page => nil, :count => nil }.should_not raise_error
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should guess the total count" do
|
46
|
+
Animal.expects(:all).returns(Array.new(2))
|
47
|
+
Animal.expects(:count).never
|
48
|
+
|
49
|
+
result = Animal.paginate :page => 2, :per_page => 4
|
50
|
+
result.total_entries.should == 6
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should guess that there are no records" do
|
54
|
+
Animal.expects(:all).returns([])
|
55
|
+
Animal.expects(:count).never
|
56
|
+
|
57
|
+
result = Animal.paginate :page => 1, :per_page => 4
|
58
|
+
result.total_entries.should == 0
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
DataMapper.setup :default, 'sqlite3::memory:'
|
3
|
+
|
4
|
+
# Define models
|
5
|
+
class Animal
|
6
|
+
include DataMapper::Resource
|
7
|
+
property :id, Serial
|
8
|
+
property :name, String
|
9
|
+
property :notes, Text
|
10
|
+
|
11
|
+
def self.setup
|
12
|
+
Animal.create(:name => 'Dog', :notes => "Man's best friend")
|
13
|
+
Animal.create(:name => 'Cat', :notes => "Woman's best friend")
|
14
|
+
Animal.create(:name => 'Lion', :notes => 'King of the Jungle')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Load fixtures
|
19
|
+
Animal.auto_migrate!
|
20
|
+
Animal.setup
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'will_paginate/finders/sequel'
|
3
|
+
require File.expand_path('../sequel_test_connector', __FILE__)
|
4
|
+
|
5
|
+
describe Sequel::Dataset::Pagination, 'extension' do
|
6
|
+
|
7
|
+
class Car < Sequel::Model
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should have the #paginate method" do
|
11
|
+
Car.should respond_to(:paginate)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should NOT have the #paginate_by_sql method" do
|
15
|
+
Car.should_not respond_to(:paginate_by_sql)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'pagination' do
|
19
|
+
before(:all) do
|
20
|
+
Car.create(:name => 'Shelby', :notes => "Man's best friend")
|
21
|
+
Car.create(:name => 'Aston Martin', :notes => "Woman's best friend")
|
22
|
+
Car.create(:name => 'Corvette', :notes => 'King of the Jungle')
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should imitate WillPaginate::Collection" do
|
26
|
+
result = Car.paginate(1, 2)
|
27
|
+
|
28
|
+
result.total_entries.should == 3
|
29
|
+
result.total_pages.should == 2
|
30
|
+
result.per_page.should == 2
|
31
|
+
result.current_page.should == 1
|
32
|
+
result.previous_page.should be_nil
|
33
|
+
result.next_page.should == 2
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should perform" do
|
37
|
+
Car.paginate(1, 2).all.should == [Car[1], Car[2]]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should perform with #select and #order" do
|
41
|
+
result = Car.select("name as foo".lit).order(:name).paginate(1, 2).all
|
42
|
+
result.size.should == 2
|
43
|
+
result.first.values[:foo].should == "Aston Martin"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should perform with #filter" do
|
47
|
+
results = Car.filter(:name => 'Shelby').paginate(1, 2).all
|
48
|
+
results.size.should == 1
|
49
|
+
results.first.should == Car.find(:name => 'Shelby')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'will_paginate/finders/base'
|
3
|
+
|
4
|
+
class Model
|
5
|
+
extend WillPaginate::Finders::Base
|
6
|
+
end
|
7
|
+
|
8
|
+
describe WillPaginate::Finders::Base do
|
9
|
+
it "should define default per_page of 30" do
|
10
|
+
Model.per_page.should == 30
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should allow to set custom per_page" do
|
14
|
+
begin
|
15
|
+
Model.per_page = 25
|
16
|
+
Model.per_page.should == 25
|
17
|
+
ensure
|
18
|
+
Model.per_page = 30
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should result with WillPaginate::Collection" do
|
23
|
+
Model.expects(:wp_query)
|
24
|
+
Model.paginate(:page => nil).should be_instance_of(WillPaginate::Collection)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should delegate pagination to wp_query" do
|
28
|
+
Model.expects(:wp_query).with({}, instance_of(WillPaginate::Collection), [])
|
29
|
+
Model.paginate :page => nil
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should complain when no hash parameters given" do
|
33
|
+
lambda {
|
34
|
+
Model.paginate
|
35
|
+
}.should raise_error(ArgumentError, 'parameter hash expected')
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should complain when no :page parameter present" do
|
39
|
+
lambda {
|
40
|
+
Model.paginate :per_page => 6
|
41
|
+
}.should raise_error(ArgumentError, ':page parameter required')
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should complain when both :count and :total_entries are given" do
|
45
|
+
lambda {
|
46
|
+
Model.paginate :page => 1, :count => {}, :total_entries => 1
|
47
|
+
}.should raise_error(ArgumentError, ':count and :total_entries are mutually exclusive')
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should never mangle options" do
|
51
|
+
options = { :page => 1 }
|
52
|
+
options.expects(:delete).never
|
53
|
+
options_before = options.dup
|
54
|
+
|
55
|
+
Model.expects(:wp_query)
|
56
|
+
Model.paginate(options)
|
57
|
+
|
58
|
+
options.should == options_before
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should provide paginated_each functionality" do
|
62
|
+
collection = stub('collection', :size => 5, :empty? => false, :per_page => 5)
|
63
|
+
collection.expects(:each).times(2).returns(collection)
|
64
|
+
last_collection = stub('collection', :size => 4, :empty? => false, :per_page => 5)
|
65
|
+
last_collection.expects(:each).returns(last_collection)
|
66
|
+
|
67
|
+
params = { :order => 'id', :total_entries => 0 }
|
68
|
+
|
69
|
+
Model.expects(:paginate).with(params.merge(:page => 2)).returns(collection)
|
70
|
+
Model.expects(:paginate).with(params.merge(:page => 3)).returns(collection)
|
71
|
+
Model.expects(:paginate).with(params.merge(:page => 4)).returns(last_collection)
|
72
|
+
|
73
|
+
total = Model.paginated_each(:page => '2') { }
|
74
|
+
total.should == 14
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Developer < User
|
2
|
+
has_and_belongs_to_many :projects, :include => :topics, :order => 'projects.name'
|
3
|
+
|
4
|
+
def self.with_poor_ones(&block)
|
5
|
+
with_scope :find => { :conditions => ['salary <= ?', 80000], :order => 'salary' } do
|
6
|
+
yield
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
scope :poor, :conditions => ['salary <= ?', 80000], :order => 'salary'
|
11
|
+
|
12
|
+
def self.per_page() 10 end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Project < ActiveRecord::Base
|
2
|
+
has_and_belongs_to_many :developers, :uniq => true
|
3
|
+
|
4
|
+
has_many :topics
|
5
|
+
# :finder_sql => 'SELECT * FROM topics WHERE (topics.project_id = #{id})',
|
6
|
+
# :counter_sql => 'SELECT COUNT(*) FROM topics WHERE (topics.project_id = #{id})'
|
7
|
+
|
8
|
+
has_many :replies, :through => :topics do
|
9
|
+
def only_recent(params = {})
|
10
|
+
scoped.where(['replies.created_at > ?', 15.minutes.ago])
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|