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,113 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'active_record/fixtures'
|
3
|
+
require 'active_support/multibyte' # needed for Ruby 1.9.1
|
4
|
+
|
5
|
+
$query_count = 0
|
6
|
+
$query_sql = []
|
7
|
+
|
8
|
+
ignore_sql = /
|
9
|
+
^(
|
10
|
+
PRAGMA | SHOW\ max_identifier_length |
|
11
|
+
SELECT\ (currval|CAST|@@IDENTITY|@@ROWCOUNT) |
|
12
|
+
SHOW\ (FIELDS|TABLES)
|
13
|
+
)\b |
|
14
|
+
\bFROM\ (sqlite_master|pg_tables|pg_attribute)\b
|
15
|
+
/x
|
16
|
+
|
17
|
+
ActiveSupport::Notifications.subscribe(/^sql\./) do |*args|
|
18
|
+
payload = args.last
|
19
|
+
unless payload[:name] =~ /^Fixture/ or payload[:sql] =~ ignore_sql
|
20
|
+
$query_count += 1
|
21
|
+
$query_sql << payload[:sql]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module ActiverecordTestConnector
|
26
|
+
extend self
|
27
|
+
|
28
|
+
attr_accessor :able_to_connect
|
29
|
+
attr_accessor :connected
|
30
|
+
|
31
|
+
FIXTURES_PATH = File.expand_path('../../fixtures', __FILE__)
|
32
|
+
|
33
|
+
Fixtures = defined?(ActiveRecord::Fixtures) ? ActiveRecord::Fixtures : ::Fixtures
|
34
|
+
|
35
|
+
# Set our defaults
|
36
|
+
self.connected = false
|
37
|
+
self.able_to_connect = true
|
38
|
+
|
39
|
+
def setup
|
40
|
+
unless self.connected || !self.able_to_connect
|
41
|
+
setup_connection
|
42
|
+
load_schema
|
43
|
+
add_load_path FIXTURES_PATH
|
44
|
+
self.connected = true
|
45
|
+
end
|
46
|
+
rescue Exception => e # errors from ActiveRecord setup
|
47
|
+
$stderr.puts "\nSkipping ActiveRecord tests: #{e}\n\n"
|
48
|
+
self.able_to_connect = false
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def add_load_path(path)
|
54
|
+
dep = defined?(ActiveSupport::Dependencies) ? ActiveSupport::Dependencies : ::Dependencies
|
55
|
+
dep.autoload_paths.unshift path
|
56
|
+
end
|
57
|
+
|
58
|
+
def setup_connection
|
59
|
+
db = ENV['DB'].blank?? 'sqlite3' : ENV['DB']
|
60
|
+
|
61
|
+
configurations = YAML.load_file(File.expand_path('../../database.yml', __FILE__))
|
62
|
+
raise "no configuration for '#{db}'" unless configurations.key? db
|
63
|
+
configuration = configurations[db]
|
64
|
+
|
65
|
+
# ActiveRecord::Base.logger = Logger.new(STDOUT) if $0 == 'irb'
|
66
|
+
puts "using #{configuration['adapter']} adapter"
|
67
|
+
|
68
|
+
ActiveRecord::Base.configurations = { db => configuration }
|
69
|
+
ActiveRecord::Base.establish_connection(db)
|
70
|
+
ActiveRecord::Base.default_timezone = :utc
|
71
|
+
end
|
72
|
+
|
73
|
+
def load_schema
|
74
|
+
ActiveRecord::Base.silence do
|
75
|
+
ActiveRecord::Migration.verbose = false
|
76
|
+
load File.join(FIXTURES_PATH, 'schema.rb')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
module FixtureSetup
|
81
|
+
def fixtures(*tables)
|
82
|
+
table_names = tables.map { |t| t.to_s }
|
83
|
+
|
84
|
+
fixtures = Fixtures.create_fixtures ActiverecordTestConnector::FIXTURES_PATH, table_names
|
85
|
+
@@loaded_fixtures = {}
|
86
|
+
@@fixture_cache = {}
|
87
|
+
|
88
|
+
unless fixtures.nil?
|
89
|
+
if fixtures.instance_of?(Fixtures)
|
90
|
+
@@loaded_fixtures[fixtures.table_name] = fixtures
|
91
|
+
else
|
92
|
+
fixtures.each { |f| @@loaded_fixtures[f.table_name] = f }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
table_names.each do |table_name|
|
97
|
+
define_method(table_name) do |*fixtures|
|
98
|
+
@@fixture_cache[table_name] ||= {}
|
99
|
+
|
100
|
+
instances = fixtures.map do |fixture|
|
101
|
+
if @@loaded_fixtures[table_name][fixture.to_s]
|
102
|
+
@@fixture_cache[table_name][fixture] ||= @@loaded_fixtures[table_name][fixture.to_s].find
|
103
|
+
else
|
104
|
+
raise StandardError, "No fixture with name '#{fixture}' found for table '#{table_name}'"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
instances.size == 1 ? instances.first : instances
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'will_paginate/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
|
12
|
+
|
13
|
+
describe WillPaginate::DataMapper do
|
14
|
+
|
15
|
+
it "has per_page" do
|
16
|
+
Animal.per_page.should == 30
|
17
|
+
begin
|
18
|
+
Animal.per_page = 10
|
19
|
+
Animal.per_page.should == 10
|
20
|
+
|
21
|
+
subclass = Class.new(Animal)
|
22
|
+
subclass.per_page.should == 10
|
23
|
+
ensure
|
24
|
+
Animal.per_page = 30
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it "doesn't make normal collections appear paginated" do
|
29
|
+
Animal.all.should_not be_paginated
|
30
|
+
end
|
31
|
+
|
32
|
+
it "paginates to first page by default" do
|
33
|
+
animals = Animal.paginate(:page => nil)
|
34
|
+
|
35
|
+
animals.should be_paginated
|
36
|
+
animals.current_page.should == 1
|
37
|
+
animals.per_page.should == 30
|
38
|
+
animals.offset.should == 0
|
39
|
+
animals.total_entries.should == 3
|
40
|
+
animals.total_pages.should == 1
|
41
|
+
end
|
42
|
+
|
43
|
+
it "paginates to first page, explicit limit" do
|
44
|
+
animals = Animal.paginate(:page => 1, :per_page => 2)
|
45
|
+
|
46
|
+
animals.current_page.should == 1
|
47
|
+
animals.per_page.should == 2
|
48
|
+
animals.total_entries.should == 3
|
49
|
+
animals.total_pages.should == 2
|
50
|
+
animals.map {|a| a.name }.should == %w[ Dog Cat ]
|
51
|
+
end
|
52
|
+
|
53
|
+
it "paginates to second page" do
|
54
|
+
animals = Animal.paginate(:page => 2, :per_page => 2)
|
55
|
+
|
56
|
+
animals.current_page.should == 2
|
57
|
+
animals.offset.should == 2
|
58
|
+
animals.map {|a| a.name }.should == %w[ Lion ]
|
59
|
+
end
|
60
|
+
|
61
|
+
it "paginates a collection" do
|
62
|
+
friends = Animal.all(:notes.like => '%friend%')
|
63
|
+
friends.paginate(:page => 1).per_page.should == 30
|
64
|
+
friends.paginate(:page => 1, :per_page => 1).total_entries.should == 2
|
65
|
+
end
|
66
|
+
|
67
|
+
it "paginates a limited collection" do
|
68
|
+
animals = Animal.all(:limit => 2).paginate(:page => 1)
|
69
|
+
animals.per_page.should == 2
|
70
|
+
end
|
71
|
+
|
72
|
+
it "has page() method" do
|
73
|
+
Animal.page(2).per_page.should == 30
|
74
|
+
Animal.page(2).offset.should == 30
|
75
|
+
Animal.page(2).current_page.should == 2
|
76
|
+
Animal.all(:limit => 2).page(2).per_page.should == 2
|
77
|
+
end
|
78
|
+
|
79
|
+
it "has total_pages at 1 for empty collections" do
|
80
|
+
Animal.all(:conditions => ['1=2']).page(1).total_pages.should == 1
|
81
|
+
end
|
82
|
+
|
83
|
+
it "can iterate and then call WP methods" do
|
84
|
+
animals = Animal.all(:limit => 2).page(1)
|
85
|
+
animals.each { |a| }
|
86
|
+
animals.total_entries.should == 3
|
87
|
+
end
|
88
|
+
|
89
|
+
it "augments to_a to return a WP::Collection" do
|
90
|
+
animals = Animal.all(:limit => 2).page(1)
|
91
|
+
array = animals.to_a
|
92
|
+
array.size.should == 2
|
93
|
+
array.is_a? WillPaginate::Collection
|
94
|
+
array.current_page.should == 1
|
95
|
+
array.per_page.should == 2
|
96
|
+
end
|
97
|
+
|
98
|
+
it "doesn't have a problem assigning has-one-through relationship" do
|
99
|
+
human = Human.create :name => "Mislav"
|
100
|
+
human.pet = Animal.first
|
101
|
+
end
|
102
|
+
|
103
|
+
end if datamapper_loaded
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'sqlite3'
|
2
|
+
require 'dm-core'
|
3
|
+
require 'dm-core/support/logger'
|
4
|
+
require 'dm-migrations'
|
5
|
+
|
6
|
+
DataMapper.setup :default, 'sqlite3::memory:'
|
7
|
+
|
8
|
+
# Define models
|
9
|
+
class Animal
|
10
|
+
include DataMapper::Resource
|
11
|
+
property :id, Serial
|
12
|
+
property :name, String
|
13
|
+
property :notes, Text
|
14
|
+
|
15
|
+
def self.setup
|
16
|
+
Animal.create(:name => 'Dog', :notes => "Man's best friend")
|
17
|
+
Animal.create(:name => 'Cat', :notes => "Woman's best friend")
|
18
|
+
Animal.create(:name => 'Lion', :notes => 'King of the Jungle')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Ownership
|
23
|
+
include DataMapper::Resource
|
24
|
+
|
25
|
+
belongs_to :animal, :key => true
|
26
|
+
belongs_to :human, :key => true
|
27
|
+
|
28
|
+
def self.setup
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Human
|
33
|
+
include DataMapper::Resource
|
34
|
+
|
35
|
+
property :id, Serial
|
36
|
+
property :name, String
|
37
|
+
|
38
|
+
has n, :ownerships
|
39
|
+
has 1, :pet, :model => 'Animal', :through => :ownerships, :via => :animal
|
40
|
+
|
41
|
+
def self.setup
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Load fixtures
|
46
|
+
[Animal, Ownership, Human].each do |klass|
|
47
|
+
klass.auto_migrate!
|
48
|
+
klass.setup
|
49
|
+
end
|
50
|
+
|
51
|
+
if 'irb' == $0
|
52
|
+
DataMapper.logger.set_log($stdout, :debug)
|
53
|
+
DataMapper.logger.auto_flush = true
|
54
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'will_paginate/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
|
12
|
+
|
13
|
+
describe Sequel::Dataset::Pagination, 'extension' do
|
14
|
+
|
15
|
+
class Car < Sequel::Model
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should have the #paginate method" do
|
19
|
+
Car.should respond_to(:paginate)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should NOT have the #paginate_by_sql method" do
|
23
|
+
Car.should_not respond_to(:paginate_by_sql)
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'pagination' do
|
27
|
+
before(:all) do
|
28
|
+
Car.create(:name => 'Shelby', :notes => "Man's best friend")
|
29
|
+
Car.create(:name => 'Aston Martin', :notes => "Woman's best friend")
|
30
|
+
Car.create(:name => 'Corvette', :notes => 'King of the Jungle')
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should imitate WillPaginate::Collection" do
|
34
|
+
result = Car.paginate(1, 2)
|
35
|
+
|
36
|
+
result.should_not be_empty
|
37
|
+
result.size.should == 2
|
38
|
+
result.length.should == 2
|
39
|
+
result.total_entries.should == 3
|
40
|
+
result.total_pages.should == 2
|
41
|
+
result.per_page.should == 2
|
42
|
+
result.current_page.should == 1
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should perform" do
|
46
|
+
Car.paginate(1, 2).all.should == [Car[1], Car[2]]
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should be empty" do
|
50
|
+
result = Car.paginate(3, 2)
|
51
|
+
result.should be_empty
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should perform with #select and #order" do
|
55
|
+
result = Car.select("name as foo".lit).order(:name).paginate(1, 2).all
|
56
|
+
result.size.should == 2
|
57
|
+
result.first.values[:foo].should == "Aston Martin"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should perform with #filter" do
|
61
|
+
results = Car.filter(:name => 'Shelby').paginate(1, 2).all
|
62
|
+
results.size.should == 1
|
63
|
+
results.first.should == Car.find(:name => 'Shelby')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end if sequel_loaded
|
@@ -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,15 @@
|
|
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
|
+
|
14
|
+
has_many :unique_replies, :through => :topics, :source => :replies, :uniq => true
|
15
|
+
end
|
@@ -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.utc.to_s(:db) %>
|
6
|
+
|
7
|
+
another:
|
8
|
+
id: 2
|
9
|
+
topic_id: 2
|
10
|
+
content: Nuh uh!
|
11
|
+
created_at: <%= 1.hour.ago.utc.to_s(:db) %>
|
12
|
+
|
13
|
+
spam:
|
14
|
+
id: 3
|
15
|
+
topic_id: 1
|
16
|
+
content: Nice site!
|
17
|
+
created_at: <%= 1.hour.ago.utc.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.utc.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.utc.to_s(:db) %>
|