will_paginate_seo 3.0.4

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.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +18 -0
  3. data/README.md +61 -0
  4. data/lib/will_paginate.rb +25 -0
  5. data/lib/will_paginate/active_record.rb +261 -0
  6. data/lib/will_paginate/array.rb +33 -0
  7. data/lib/will_paginate/collection.rb +136 -0
  8. data/lib/will_paginate/core_ext.rb +30 -0
  9. data/lib/will_paginate/data_mapper.rb +100 -0
  10. data/lib/will_paginate/deprecation.rb +55 -0
  11. data/lib/will_paginate/i18n.rb +22 -0
  12. data/lib/will_paginate/locale/en.yml +33 -0
  13. data/lib/will_paginate/mongoid.rb +46 -0
  14. data/lib/will_paginate/page_number.rb +57 -0
  15. data/lib/will_paginate/per_page.rb +27 -0
  16. data/lib/will_paginate/railtie.rb +68 -0
  17. data/lib/will_paginate/sequel.rb +39 -0
  18. data/lib/will_paginate/version.rb +9 -0
  19. data/lib/will_paginate/view_helpers.rb +162 -0
  20. data/lib/will_paginate/view_helpers/action_view.rb +152 -0
  21. data/lib/will_paginate/view_helpers/link_renderer.rb +131 -0
  22. data/lib/will_paginate/view_helpers/link_renderer_base.rb +77 -0
  23. data/lib/will_paginate/view_helpers/merb.rb +26 -0
  24. data/lib/will_paginate/view_helpers/sinatra.rb +41 -0
  25. data/spec/collection_spec.rb +139 -0
  26. data/spec/console +12 -0
  27. data/spec/console_fixtures.rb +28 -0
  28. data/spec/database.yml +22 -0
  29. data/spec/fake_rubygems.rb +18 -0
  30. data/spec/finders/active_record_spec.rb +517 -0
  31. data/spec/finders/activerecord_test_connector.rb +119 -0
  32. data/spec/finders/data_mapper_spec.rb +116 -0
  33. data/spec/finders/data_mapper_test_connector.rb +54 -0
  34. data/spec/finders/mongoid_spec.rb +140 -0
  35. data/spec/finders/sequel_spec.rb +67 -0
  36. data/spec/finders/sequel_test_connector.rb +15 -0
  37. data/spec/fixtures/admin.rb +3 -0
  38. data/spec/fixtures/developer.rb +16 -0
  39. data/spec/fixtures/developers_projects.yml +13 -0
  40. data/spec/fixtures/project.rb +13 -0
  41. data/spec/fixtures/projects.yml +6 -0
  42. data/spec/fixtures/replies.yml +29 -0
  43. data/spec/fixtures/reply.rb +8 -0
  44. data/spec/fixtures/schema.rb +38 -0
  45. data/spec/fixtures/topic.rb +8 -0
  46. data/spec/fixtures/topics.yml +30 -0
  47. data/spec/fixtures/user.rb +2 -0
  48. data/spec/fixtures/users.yml +35 -0
  49. data/spec/matchers/deprecation_matcher.rb +27 -0
  50. data/spec/matchers/phrase_matcher.rb +19 -0
  51. data/spec/matchers/query_count_matcher.rb +36 -0
  52. data/spec/page_number_spec.rb +65 -0
  53. data/spec/per_page_spec.rb +41 -0
  54. data/spec/spec_helper.rb +46 -0
  55. data/spec/view_helpers/action_view_spec.rb +441 -0
  56. data/spec/view_helpers/base_spec.rb +142 -0
  57. data/spec/view_helpers/link_renderer_base_spec.rb +87 -0
  58. data/spec/view_helpers/view_example_group.rb +125 -0
  59. metadata +106 -0
@@ -0,0 +1,119 @@
1
+ require 'active_record'
2
+ require 'active_record/fixtures'
3
+ require 'active_support/multibyte' # needed for Ruby 1.9.1
4
+ require 'stringio'
5
+
6
+ $query_count = 0
7
+ $query_sql = []
8
+
9
+ ignore_sql = /
10
+ ^(
11
+ PRAGMA | SHOW\ max_identifier_length |
12
+ SELECT\ (currval|CAST|@@IDENTITY|@@ROWCOUNT) |
13
+ SHOW\ ((FULL\ )?FIELDS|TABLES)
14
+ )\b |
15
+ \bFROM\ (sqlite_master|pg_tables|pg_attribute)\b
16
+ /x
17
+
18
+ ActiveSupport::Notifications.subscribe(/^sql\./) do |*args|
19
+ payload = args.last
20
+ unless payload[:name] =~ /^Fixture/ or payload[:sql] =~ ignore_sql
21
+ $query_count += 1
22
+ $query_sql << payload[:sql]
23
+ end
24
+ end
25
+
26
+ module ActiverecordTestConnector
27
+ extend self
28
+
29
+ attr_accessor :able_to_connect
30
+ attr_accessor :connected
31
+
32
+ FIXTURES_PATH = File.expand_path('../../fixtures', __FILE__)
33
+
34
+ Fixtures = defined?(ActiveRecord::FixtureSet) ? ActiveRecord::FixtureSet :
35
+ defined?(ActiveRecord::Fixtures) ? ActiveRecord::Fixtures :
36
+ ::Fixtures
37
+
38
+ # Set our defaults
39
+ self.connected = false
40
+ self.able_to_connect = true
41
+
42
+ def setup
43
+ unless self.connected || !self.able_to_connect
44
+ setup_connection
45
+ load_schema
46
+ add_load_path FIXTURES_PATH
47
+ self.connected = true
48
+ end
49
+ rescue Exception => e # errors from ActiveRecord setup
50
+ $stderr.puts "\nSkipping ActiveRecord tests: #{e}\n\n"
51
+ self.able_to_connect = false
52
+ end
53
+
54
+ private
55
+
56
+ def add_load_path(path)
57
+ dep = defined?(ActiveSupport::Dependencies) ? ActiveSupport::Dependencies : ::Dependencies
58
+ dep.autoload_paths.unshift path
59
+ end
60
+
61
+ def setup_connection
62
+ db = ENV['DB'].blank?? 'sqlite3' : ENV['DB']
63
+
64
+ configurations = YAML.load_file(File.expand_path('../../database.yml', __FILE__))
65
+ raise "no configuration for '#{db}'" unless configurations.key? db
66
+ configuration = configurations[db]
67
+
68
+ # ActiveRecord::Base.logger = Logger.new(STDOUT) if $0 == 'irb'
69
+ puts "using #{configuration['adapter']} adapter"
70
+
71
+ ActiveRecord::Base.configurations = { db => configuration }
72
+ ActiveRecord::Base.establish_connection(db.to_sym)
73
+ ActiveRecord::Base.default_timezone = :utc
74
+ end
75
+
76
+ def load_schema
77
+ begin
78
+ $stdout = StringIO.new
79
+ ActiveRecord::Migration.verbose = false
80
+ load File.join(FIXTURES_PATH, 'schema.rb')
81
+ ensure
82
+ $stdout = STDOUT
83
+ end
84
+ end
85
+
86
+ module FixtureSetup
87
+ def fixtures(*tables)
88
+ table_names = tables.map { |t| t.to_s }
89
+
90
+ fixtures = Fixtures.create_fixtures ActiverecordTestConnector::FIXTURES_PATH, table_names
91
+ @@loaded_fixtures = {}
92
+ @@fixture_cache = {}
93
+
94
+ unless fixtures.nil?
95
+ if fixtures.instance_of?(Fixtures)
96
+ @@loaded_fixtures[fixtures.table_name] = fixtures
97
+ else
98
+ fixtures.each { |f| @@loaded_fixtures[f.table_name] = f }
99
+ end
100
+ end
101
+
102
+ table_names.each do |table_name|
103
+ define_method(table_name) do |*fixtures|
104
+ @@fixture_cache[table_name] ||= {}
105
+
106
+ instances = fixtures.map do |fixture|
107
+ if @@loaded_fixtures[table_name][fixture.to_s]
108
+ @@fixture_cache[table_name][fixture] ||= @@loaded_fixtures[table_name][fixture.to_s].find
109
+ else
110
+ raise StandardError, "No fixture with name '#{fixture}' found for table '#{table_name}'"
111
+ end
112
+ end
113
+
114
+ instances.size == 1 ? instances.first : instances
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,116 @@
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 "overrides total_entries count with a fixed value" do
84
+ lambda {
85
+ animals = Animal.paginate :page => 1, :per_page => 3, :total_entries => 999
86
+ animals.total_entries.should == 999
87
+ }.should run_queries(0)
88
+ end
89
+
90
+ it "supports a non-int for total_entries" do
91
+ topics = Animal.paginate :page => 1, :per_page => 3, :total_entries => "999"
92
+ topics.total_entries.should == 999
93
+ end
94
+
95
+
96
+ it "can iterate and then call WP methods" do
97
+ animals = Animal.all(:limit => 2).page(1)
98
+ animals.each { |a| }
99
+ animals.total_entries.should == 3
100
+ end
101
+
102
+ it "augments to_a to return a WP::Collection" do
103
+ animals = Animal.all(:limit => 2).page(1)
104
+ array = animals.to_a
105
+ array.size.should == 2
106
+ array.should be_kind_of(WillPaginate::Collection)
107
+ array.current_page.should == 1
108
+ array.per_page.should == 2
109
+ end
110
+
111
+ it "doesn't have a problem assigning has-one-through relationship" do
112
+ human = Human.create :name => "Mislav"
113
+ human.pet = Animal.first
114
+ end
115
+
116
+ 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,140 @@
1
+ require 'spec_helper'
2
+
3
+ begin
4
+ require 'will_paginate/mongoid'
5
+ rescue LoadError => error
6
+ warn "Error running Sequel specs: #{error.message}"
7
+ mongoid_loaded = false
8
+ else
9
+ Mongoid.database = Mongo::Connection.new.db('will_paginate_test')
10
+
11
+ class MongoidModel
12
+ include Mongoid::Document
13
+ end
14
+
15
+ mongoid_loaded = true
16
+ end
17
+
18
+ describe WillPaginate::Mongoid do
19
+ before(:all) do
20
+ MongoidModel.delete_all
21
+ 4.times { MongoidModel.create! }
22
+ end
23
+
24
+ let(:criteria) { MongoidModel.criteria }
25
+
26
+ describe "#page" do
27
+ it "should forward to the paginate method" do
28
+ criteria.expects(:paginate).with(:page => 2).returns("itself")
29
+ criteria.page(2).should == "itself"
30
+ end
31
+
32
+ it "should not override per_page if set earlier in the chain" do
33
+ criteria.paginate(:per_page => 10).page(1).per_page.should == 10
34
+ criteria.paginate(:per_page => 20).page(1).per_page.should == 20
35
+ end
36
+ end
37
+
38
+ describe "#per_page" do
39
+ it "should set the limit if given an argument" do
40
+ criteria.per_page(10).options[:limit].should == 10
41
+ end
42
+
43
+ it "should return the current limit if no argument is given" do
44
+ criteria.per_page.should == nil
45
+ criteria.per_page(10).per_page.should == 10
46
+ end
47
+
48
+ it "should be interchangable with limit" do
49
+ criteria.limit(15).per_page.should == 15
50
+ end
51
+
52
+ it "should be nil'able" do
53
+ criteria.per_page(nil).per_page.should be_nil
54
+ end
55
+ end
56
+
57
+ describe "#paginate" do
58
+ it "should use criteria" do
59
+ criteria.paginate.should be_instance_of(::Mongoid::Criteria)
60
+ end
61
+
62
+ it "should not override page number if set earlier in the chain" do
63
+ criteria.page(3).paginate.current_page.should == 3
64
+ end
65
+
66
+ it "should limit according to per_page parameter" do
67
+ criteria.paginate(:per_page => 10).options.should include(:limit => 10)
68
+ end
69
+
70
+ it "should skip according to page and per_page parameters" do
71
+ criteria.paginate(:page => 2, :per_page => 5).options.should include(:skip => 5)
72
+ end
73
+
74
+ specify "first fallback value for per_page option is the current limit" do
75
+ criteria.limit(12).paginate.options.should include(:limit => 12)
76
+ end
77
+
78
+ specify "second fallback value for per_page option is WillPaginate.per_page" do
79
+ criteria.paginate.options.should include(:limit => WillPaginate.per_page)
80
+ end
81
+
82
+ specify "page should default to 1" do
83
+ criteria.paginate.options.should include(:skip => 0)
84
+ end
85
+
86
+ it "should convert strings to integers" do
87
+ criteria.paginate(:page => "2", :per_page => "3").options.should include(:limit => 3, :limit => 3)
88
+ end
89
+
90
+ describe "collection compatibility" do
91
+ describe "#total_count" do
92
+ it "should be calculated correctly" do
93
+ criteria.paginate(:per_page => 1).total_entries.should == 4
94
+ criteria.paginate(:per_page => 3).total_entries.should == 4
95
+ end
96
+
97
+ it "should be cached" do
98
+ criteria.expects(:count).once.returns(123)
99
+ criteria.paginate
100
+ 2.times { criteria.total_entries.should == 123 }
101
+ end
102
+ end
103
+
104
+ it "should calculate total_pages" do
105
+ criteria.paginate(:per_page => 1).total_pages.should == 4
106
+ criteria.paginate(:per_page => 3).total_pages.should == 2
107
+ criteria.paginate(:per_page => 10).total_pages.should == 1
108
+ end
109
+
110
+ it "should return per_page" do
111
+ criteria.paginate(:per_page => 1).per_page.should == 1
112
+ criteria.paginate(:per_page => 5).per_page.should == 5
113
+ end
114
+
115
+ describe "#current_page" do
116
+ it "should return current_page" do
117
+ criteria.paginate(:page => 1).current_page.should == 1
118
+ criteria.paginate(:page => 3).current_page.should == 3
119
+ end
120
+
121
+ it "should be casted to PageNumber" do
122
+ criteria.paginate(:page => 1).current_page.should be_instance_of(WillPaginate::PageNumber)
123
+ end
124
+ end
125
+
126
+ it "should return offset" do
127
+ criteria.paginate(:page => 1).offset.should == 0
128
+ criteria.paginate(:page => 2, :per_page => 5).offset.should == 5
129
+ criteria.paginate(:page => 3, :per_page => 10).offset.should == 20
130
+ end
131
+
132
+ it "should not pollute plain mongoid criterias" do
133
+ %w(total_entries total_pages current_page).each do |method|
134
+ criteria.should_not respond_to(method)
135
+ end
136
+ criteria.offset.should be_nil # this is already a criteria method
137
+ end
138
+ end
139
+ end
140
+ end if mongoid_loaded
@@ -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