mislav-will_paginate 2.2.3

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 (43) hide show
  1. data/CHANGELOG +62 -0
  2. data/LICENSE +18 -0
  3. data/README.rdoc +135 -0
  4. data/Rakefile +110 -0
  5. data/examples/apple-circle.gif +0 -0
  6. data/examples/index.haml +69 -0
  7. data/examples/index.html +92 -0
  8. data/examples/pagination.css +90 -0
  9. data/examples/pagination.sass +91 -0
  10. data/init.rb +1 -0
  11. data/lib/will_paginate.rb +86 -0
  12. data/lib/will_paginate/array.rb +16 -0
  13. data/lib/will_paginate/collection.rb +145 -0
  14. data/lib/will_paginate/core_ext.rb +32 -0
  15. data/lib/will_paginate/finder.rb +239 -0
  16. data/lib/will_paginate/named_scope.rb +132 -0
  17. data/lib/will_paginate/named_scope_patch.rb +39 -0
  18. data/lib/will_paginate/version.rb +9 -0
  19. data/lib/will_paginate/view_helpers.rb +341 -0
  20. data/test/boot.rb +21 -0
  21. data/test/collection_test.rb +140 -0
  22. data/test/console +8 -0
  23. data/test/database.yml +22 -0
  24. data/test/finder_test.rb +416 -0
  25. data/test/fixtures/admin.rb +3 -0
  26. data/test/fixtures/developer.rb +13 -0
  27. data/test/fixtures/developers_projects.yml +13 -0
  28. data/test/fixtures/project.rb +15 -0
  29. data/test/fixtures/projects.yml +6 -0
  30. data/test/fixtures/replies.yml +29 -0
  31. data/test/fixtures/reply.rb +7 -0
  32. data/test/fixtures/schema.rb +38 -0
  33. data/test/fixtures/topic.rb +6 -0
  34. data/test/fixtures/topics.yml +30 -0
  35. data/test/fixtures/user.rb +2 -0
  36. data/test/fixtures/users.yml +35 -0
  37. data/test/helper.rb +37 -0
  38. data/test/lib/activerecord_test_case.rb +36 -0
  39. data/test/lib/activerecord_test_connector.rb +69 -0
  40. data/test/lib/load_fixtures.rb +11 -0
  41. data/test/lib/view_test_process.rb +157 -0
  42. data/test/view_test.rb +278 -0
  43. metadata +130 -0
@@ -0,0 +1,3 @@
1
+ class Admin < User
2
+ has_many :companies, :finder_sql => 'SELECT * FROM companies'
3
+ 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
+ named_scope :poor, :conditions => ['salary <= ?', 80000], :order => 'salary'
11
+
12
+ def self.per_page() 10 end
13
+ end
@@ -0,0 +1,13 @@
1
+ david_action_controller:
2
+ developer_id: 1
3
+ project_id: 2
4
+ joined_on: 2004-10-10
5
+
6
+ david_active_record:
7
+ developer_id: 1
8
+ project_id: 1
9
+ joined_on: 2004-10-10
10
+
11
+ jamis_active_record:
12
+ developer_id: 2
13
+ project_id: 1
@@ -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 find_recent(params = {})
10
+ with_scope :find => { :conditions => ['replies.created_at > ?', 15.minutes.ago] } do
11
+ find :all, params
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,6 @@
1
+ active_record:
2
+ id: 1
3
+ name: Active Record
4
+ action_controller:
5
+ id: 2
6
+ name: Active Controller
@@ -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,7 @@
1
+ class Reply < ActiveRecord::Base
2
+ belongs_to :topic, :include => [:replies]
3
+
4
+ named_scope :recent, :conditions => ['replies.created_at > ?', 15.minutes.ago]
5
+
6
+ validates_presence_of :content
7
+ end
@@ -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,6 @@
1
+ class Topic < ActiveRecord::Base
2
+ has_many :replies, :dependent => :destroy, :order => 'replies.created_at DESC'
3
+ belongs_to :project
4
+
5
+ named_scope :mentions_activerecord, :conditions => ['topics.title LIKE ?', '%ActiveRecord%']
6
+ 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,2 @@
1
+ class User < ActiveRecord::Base
2
+ end
@@ -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/test/helper.rb ADDED
@@ -0,0 +1,37 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+
4
+ # gem install redgreen for colored test output
5
+ begin require 'redgreen'; rescue LoadError; end
6
+
7
+ require 'boot' unless defined?(ActiveRecord)
8
+
9
+ class Test::Unit::TestCase
10
+ protected
11
+ def assert_respond_to_all object, methods
12
+ methods.each do |method|
13
+ [method.to_s, method.to_sym].each { |m| assert_respond_to object, m }
14
+ end
15
+ end
16
+
17
+ def collect_deprecations
18
+ old_behavior = WillPaginate::Deprecation.behavior
19
+ deprecations = []
20
+ WillPaginate::Deprecation.behavior = Proc.new do |message, callstack|
21
+ deprecations << message
22
+ end
23
+ result = yield
24
+ [result, deprecations]
25
+ ensure
26
+ WillPaginate::Deprecation.behavior = old_behavior
27
+ end
28
+ end
29
+
30
+ # Wrap tests that use Mocha and skip if unavailable.
31
+ def uses_mocha(test_name)
32
+ require 'mocha' unless Object.const_defined?(:Mocha)
33
+ rescue LoadError => load_error
34
+ $stderr.puts "Skipping #{test_name} tests. `gem install mocha` and try again."
35
+ else
36
+ yield
37
+ end
@@ -0,0 +1,36 @@
1
+ require 'lib/activerecord_test_connector'
2
+
3
+ class ActiveRecordTestCase < Test::Unit::TestCase
4
+ # Set our fixture path
5
+ if ActiveRecordTestConnector.able_to_connect
6
+ self.fixture_path = File.join(File.dirname(__FILE__), '..', 'fixtures')
7
+ self.use_transactional_fixtures = true
8
+ end
9
+
10
+ def self.fixtures(*args)
11
+ super if ActiveRecordTestConnector.connected
12
+ end
13
+
14
+ def run(*args)
15
+ super if ActiveRecordTestConnector.connected
16
+ end
17
+
18
+ # Default so Test::Unit::TestCase doesn't complain
19
+ def test_truth
20
+ end
21
+
22
+ protected
23
+
24
+ def assert_queries(num = 1)
25
+ $query_count = 0
26
+ yield
27
+ ensure
28
+ assert_equal num, $query_count, "#{$query_count} instead of #{num} queries were executed."
29
+ end
30
+
31
+ def assert_no_queries(&block)
32
+ assert_queries(0, &block)
33
+ end
34
+ end
35
+
36
+ ActiveRecordTestConnector.setup
@@ -0,0 +1,69 @@
1
+ require 'active_record'
2
+ require 'active_record/version'
3
+ require 'active_record/fixtures'
4
+
5
+ class ActiveRecordTestConnector
6
+ cattr_accessor :able_to_connect
7
+ cattr_accessor :connected
8
+
9
+ FIXTURES_PATH = File.join(File.dirname(__FILE__), '..', 'fixtures')
10
+
11
+ # Set our defaults
12
+ self.connected = false
13
+ self.able_to_connect = true
14
+
15
+ def self.setup
16
+ unless self.connected || !self.able_to_connect
17
+ setup_connection
18
+ load_schema
19
+ Dependencies.load_paths.unshift FIXTURES_PATH
20
+ self.connected = true
21
+ end
22
+ rescue Exception => e # errors from ActiveRecord setup
23
+ $stderr.puts "\nSkipping ActiveRecord tests: #{e}"
24
+ $stderr.puts "Install SQLite3 to run the full test suite for will_paginate.\n\n"
25
+ self.able_to_connect = false
26
+ end
27
+
28
+ private
29
+
30
+ def self.setup_connection
31
+ db = ENV['DB'].blank?? 'sqlite3' : ENV['DB']
32
+
33
+ configurations = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'database.yml'))
34
+ raise "no configuration for '#{db}'" unless configurations.key? db
35
+ configuration = configurations[db]
36
+
37
+ ActiveRecord::Base.logger = Logger.new(STDOUT) if $0 == 'irb'
38
+ puts "using #{configuration['adapter']} adapter" unless ENV['DB'].blank?
39
+
40
+ ActiveRecord::Base.establish_connection(configuration)
41
+ ActiveRecord::Base.configurations = { db => configuration }
42
+ prepare ActiveRecord::Base.connection
43
+
44
+ unless Object.const_defined?(:QUOTED_TYPE)
45
+ Object.send :const_set, :QUOTED_TYPE, ActiveRecord::Base.connection.quote_column_name('type')
46
+ end
47
+ end
48
+
49
+ def self.load_schema
50
+ ActiveRecord::Base.silence do
51
+ ActiveRecord::Migration.verbose = false
52
+ load File.join(FIXTURES_PATH, 'schema.rb')
53
+ end
54
+ end
55
+
56
+ def self.prepare(conn)
57
+ class << conn
58
+ IGNORED_SQL = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SHOW FIELDS /]
59
+
60
+ def execute_with_counting(sql, name = nil, &block)
61
+ $query_count ||= 0
62
+ $query_count += 1 unless IGNORED_SQL.any? { |r| sql =~ r }
63
+ execute_without_counting(sql, name, &block)
64
+ end
65
+
66
+ alias_method_chain :execute, :counting
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,11 @@
1
+ require 'boot'
2
+ require 'lib/activerecord_test_connector'
3
+
4
+ # setup the connection
5
+ ActiveRecordTestConnector.setup
6
+
7
+ # load all fixtures
8
+ Fixtures.create_fixtures(ActiveRecordTestConnector::FIXTURES_PATH, ActiveRecord::Base.connection.tables)
9
+
10
+ require 'will_paginate'
11
+ WillPaginate.enable_activerecord
@@ -0,0 +1,157 @@
1
+ require 'action_controller'
2
+ require 'action_controller/test_process'
3
+
4
+ require 'will_paginate'
5
+ WillPaginate.enable_actionpack
6
+
7
+ ActionController::Routing::Routes.draw do |map|
8
+ map.connect 'dummy/page/:page', :controller => 'dummy'
9
+ map.connect 'dummy/dots/page.:page', :controller => 'dummy', :action => 'dots'
10
+ map.connect ':controller/:action/:id'
11
+ end
12
+
13
+ ActionController::Base.perform_caching = false
14
+
15
+ class WillPaginate::ViewTestCase < Test::Unit::TestCase
16
+ def setup
17
+ super
18
+ @controller = DummyController.new
19
+ @request = @controller.request
20
+ @html_result = nil
21
+ @template = '<%= will_paginate collection, options %>'
22
+
23
+ @view = ActionView::Base.new
24
+ @view.assigns['controller'] = @controller
25
+ @view.assigns['_request'] = @request
26
+ @view.assigns['_params'] = @request.params
27
+ end
28
+
29
+ def test_no_complain; end
30
+
31
+ protected
32
+
33
+ def paginate(collection = {}, options = {}, &block)
34
+ if collection.instance_of? Hash
35
+ page_options = { :page => 1, :total_entries => 11, :per_page => 4 }.merge(collection)
36
+ collection = [1].paginate(page_options)
37
+ end
38
+
39
+ locals = { :collection => collection, :options => options }
40
+
41
+ if defined? ActionView::Template
42
+ # Rails 2.1
43
+ args = [ ActionView::Template.new(@view, @template, false, locals, true, nil) ]
44
+ else
45
+ # older Rails versions
46
+ args = [nil, @template, nil, locals]
47
+ end
48
+
49
+ @html_result = @view.render_template(*args)
50
+ @html_document = HTML::Document.new(@html_result, true, false)
51
+
52
+ if block_given?
53
+ classname = options[:class] || WillPaginate::ViewHelpers.pagination_options[:class]
54
+ assert_select("div.#{classname}", 1, 'no main DIV', &block)
55
+ end
56
+ end
57
+
58
+ def response_from_page_or_rjs
59
+ @html_document.root
60
+ end
61
+
62
+ def validate_page_numbers expected, links, param_name = :page
63
+ param_pattern = /\W#{CGI.escape(param_name.to_s)}=([^&]*)/
64
+
65
+ assert_equal(expected, links.map { |e|
66
+ e['href'] =~ param_pattern
67
+ $1 ? $1.to_i : $1
68
+ })
69
+ end
70
+
71
+ def assert_links_match pattern, links = nil, numbers = nil
72
+ links ||= assert_select 'div.pagination a[href]' do |elements|
73
+ elements
74
+ end
75
+
76
+ pages = [] if numbers
77
+
78
+ links.each do |el|
79
+ assert_match pattern, el['href']
80
+ if numbers
81
+ el['href'] =~ pattern
82
+ pages << $1.to_i
83
+ end
84
+ end
85
+
86
+ assert_equal numbers, pages, "page numbers don't match" if numbers
87
+ end
88
+
89
+ def assert_no_links_match pattern
90
+ assert_select 'div.pagination a[href]' do |elements|
91
+ elements.each do |el|
92
+ assert_no_match pattern, el['href']
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ class DummyRequest
99
+ attr_accessor :symbolized_path_parameters
100
+
101
+ def initialize
102
+ @get = true
103
+ @params = {}
104
+ @symbolized_path_parameters = { :controller => 'foo', :action => 'bar' }
105
+ end
106
+
107
+ def get?
108
+ @get
109
+ end
110
+
111
+ def post
112
+ @get = false
113
+ end
114
+
115
+ def relative_url_root
116
+ ''
117
+ end
118
+
119
+ def params(more = nil)
120
+ @params.update(more) if more
121
+ @params
122
+ end
123
+ end
124
+
125
+ class DummyController
126
+ attr_reader :request
127
+ attr_accessor :controller_name
128
+
129
+ def initialize
130
+ @request = DummyRequest.new
131
+ @url = ActionController::UrlRewriter.new(@request, @request.params)
132
+ end
133
+
134
+ def url_for(params)
135
+ @url.rewrite(params)
136
+ end
137
+ end
138
+
139
+ module HTML
140
+ Node.class_eval do
141
+ def inner_text
142
+ children.map(&:inner_text).join('')
143
+ end
144
+ end
145
+
146
+ Text.class_eval do
147
+ def inner_text
148
+ self.to_s
149
+ end
150
+ end
151
+
152
+ Tag.class_eval do
153
+ def inner_text
154
+ childless?? '' : super
155
+ end
156
+ end
157
+ end