public this repo is viewable by everyone
Description: The open source social networking platform in Ruby on Rails from the author of RailsSpace
Homepage: http://insoshi.com
Clone URL: git://github.com/insoshi/insoshi.git
Got new, index working for people
Michael Hartl (author)
2 months ago
commit  204ad3eef07c89f92bd124d3399fc746f6c8db49
tree    e1553e434f62923cf11718cc0a59a4dec52f5975
parent  841b5ea6431a060f343804e6960ed67523a10659
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
0
@@ -0,0 +1,18 @@
0
+Copyright (c) 2007 PJ Hyett and Mislav Marohnić
0
+
0
+Permission is hereby granted, free of charge, to any person obtaining a copy of
0
+this software and associated documentation files (the "Software"), to deal in
0
+the Software without restriction, including without limitation the rights to
0
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
0
+the Software, and to permit persons to whom the Software is furnished to do so,
0
+subject to the following conditions:
0
+
0
+The above copyright notice and this permission notice shall be included in all
0
+copies or substantial portions of the Software.
0
+
0
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
0
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
0
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
0
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
...
1
2
 
 
 
 
 
 
 
3
4
5
...
1
2
3
4
5
6
7
8
9
10
11
12
0
@@ -1,5 +1,12 @@
0
 class PeopleController < ApplicationController
0
   
0
+ def index
0
+ @people = Person.paginate(:all, :page => params[:page])
0
+
0
+ respond_to do |format|
0
+ format.html # index.html.erb
0
+ end
0
+ end
0
   
0
   def new
0
   end
...
1
2
 
 
 
 
 
 
 
 
 
 
 
 
 
3
...
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0
@@ -1 +1,13 @@
0
-foo
0
\ No newline at end of file
0
+<% unless @people.empty? -%>
0
+ <%= will_paginate %>
0
+ <ul>
0
+ <%- @people.each do |person| -%>
0
+ <li><%= person.name %></li>
0
+ <%- end -%>
0
+ </ul>
0
+ <%= will_paginate %>
0
+<% else %>
0
+ <h2>No results to show.</h2>
0
+<% end -%>
0
+
0
+<div class="clear"></div>
0
\ No newline at end of file
...
21
22
23
 
 
 
24
25
...
21
22
23
24
25
26
27
28
0
@@ -21,4 +21,7 @@
0
                        :maxlength => Person::MAX_PASSWORD,
0
                        :value => "" %>
0
 </div>
0
+<div class="form_row">
0
+ <%= submit_tag 'Sign up' %>
0
+</div>
0
 <% end %>
0
\ No newline at end of file
...
 
 
 
 
...
1
2
3
4
0
@@ -0,0 +1,4 @@
0
+unless ActiveRecord::Base.respond_to? :paginate
0
+ require 'will_paginate'
0
+ WillPaginate.enable
0
+end
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
0
@@ -0,0 +1,61 @@
0
+require 'active_support'
0
+
0
+# = You *will* paginate!
0
+#
0
+# First read about WillPaginate::Finder::ClassMethods, then see
0
+# WillPaginate::ViewHelpers. The magical array you're handling in-between is
0
+# WillPaginate::Collection.
0
+#
0
+# Happy paginating!
0
+module WillPaginate
0
+ class << self
0
+ # shortcut for <tt>enable_actionpack; enable_activerecord</tt>
0
+ def enable
0
+ enable_actionpack
0
+ enable_activerecord
0
+ end
0
+
0
+ # mixes in WillPaginate::ViewHelpers in ActionView::Base
0
+ def enable_actionpack
0
+ return if ActionView::Base.instance_methods.include? 'will_paginate'
0
+ require 'will_paginate/view_helpers'
0
+ ActionView::Base.class_eval { include ViewHelpers }
0
+ end
0
+
0
+ # mixes in WillPaginate::Finder in ActiveRecord::Base and classes that deal
0
+ # with associations
0
+ def enable_activerecord
0
+ return if ActiveRecord::Base.respond_to? :paginate
0
+ require 'will_paginate/finder'
0
+ ActiveRecord::Base.class_eval { include Finder }
0
+
0
+ associations = ActiveRecord::Associations
0
+ collection = associations::AssociationCollection
0
+
0
+ # to support paginating finders on associations, we have to mix in the
0
+ # method_missing magic from WillPaginate::Finder::ClassMethods to AssociationProxy
0
+ # subclasses, but in a different way for Rails 1.2.x and 2.0
0
+ (collection.instance_methods.include?(:create!) ?
0
+ collection : collection.subclasses.map(&:constantize)
0
+ ).push(associations::HasManyThroughAssociation).each do |klass|
0
+ klass.class_eval do
0
+ include Finder::ClassMethods
0
+ alias_method_chain :method_missing, :paginate
0
+ end
0
+ end
0
+ end
0
+ end
0
+
0
+ module Deprecation #:nodoc:
0
+ extend ActiveSupport::Deprecation
0
+
0
+ def self.warn(message, callstack = caller)
0
+ message = 'WillPaginate: ' + message.strip.gsub(/ {3,}/, ' ')
0
+ behavior.call(message, callstack) if behavior && !silenced?
0
+ end
0
+
0
+ def self.silenced?
0
+ ActiveSupport::Deprecation.silenced?
0
+ end
0
+ end
0
+end
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
0
@@ -0,0 +1,132 @@
0
+require 'will_paginate'
0
+
0
+module WillPaginate
0
+ # = OMG, invalid page number!
0
+ # This is an ArgumentError raised in case a page was requested that is either
0
+ # zero or negative number. You should decide how do deal with such errors in
0
+ # the controller.
0
+ #
0
+ # This error is *not* raised when a page further than the last page is
0
+ # requested. Use <tt>WillPaginate::Collection#out_of_bounds?</tt> method to
0
+ # check for those cases and manually deal with them as you see fit.
0
+ class InvalidPage < ArgumentError
0
+ def initialize(page, page_num)
0
+ super "#{page.inspect} given as value, which translates to '#{page_num}' as page number"
0
+ end
0
+ end
0
+
0
+ # Arrays returned from paginating finds are, in fact, instances of this.
0
+ # You may think of WillPaginate::Collection as an ordinary array with some
0
+ # extra properties. Those properties are used by view helpers to generate
0
+ # correct page links.
0
+ #
0
+ # WillPaginate::Collection also assists in rolling out your own pagination
0
+ # solutions: see +create+.
0
+ #
0
+ class Collection < Array
0
+ attr_reader :current_page, :per_page, :total_entries
0
+
0
+ # Arguments to this constructor are the current page number, per-page limit
0
+ # and the total number of entries. The last argument is optional because it
0
+ # is best to do lazy counting; in other words, count *conditionally* after
0
+ # populating the collection using the +replace+ method.
0
+ #
0
+ def initialize(page, per_page, total = nil)
0
+ @current_page = page.to_i
0
+ raise InvalidPage.new(page, @current_page) if @current_page < 1
0
+ @per_page = per_page.to_i
0
+ raise ArgumentError, "`per_page` setting cannot be less than 1 (#{@per_page} given)" if @per_page < 1
0
+
0
+ self.total_entries = total if total
0
+ end
0
+
0
+ # Just like +new+, but yields the object after instantiation and returns it
0
+ # afterwards. This is very useful for manual pagination:
0
+ #
0
+ # @entries = WillPaginate::Collection.create(1, 10) do |pager|
0
+ # result = Post.find(:all, :limit => pager.per_page, :offset => pager.offset)
0
+ # # inject the result array into the paginated collection:
0
+ # pager.replace(result)
0
+ #
0
+ # unless pager.total_entries
0
+ # # the pager didn't manage to guess the total count, do it manually
0
+ # pager.total_entries = Post.count
0
+ # end
0
+ # end
0
+ #
0
+ # The possibilities with this are endless. For another example, here is how
0
+ # WillPaginate used to define pagination for Array instances:
0
+ #
0
+ # Array.class_eval do
0
+ # def paginate(page = 1, per_page = 15)
0
+ # WillPaginate::Collection.create(page, per_page, size) do |pager|
0
+ # pager.replace self[pager.offset, pager.per_page].to_a
0
+ # end
0
+ # end
0
+ # end
0
+ #
0
+ def self.create(page, per_page, total = nil, &block)
0
+ pager = new(page, per_page, total)
0
+ yield pager
0
+ pager
0
+ end
0
+
0
+ # The total number of pages.
0
+ def page_count
0
+ @total_pages
0
+ end
0
+
0
+ # Helper method that is true when someone tries to fetch a page with a
0
+ # larger number than the last page. Can be used in combination with flashes
0
+ # and redirecting.
0
+ def out_of_bounds?
0
+ current_page > page_count
0
+ end
0
+
0
+ # Current offset of the paginated collection. If we're on the first page,
0
+ # it is always 0. If we're on the 2nd page and there are 30 entries per page,
0
+ # the offset is 30. This property is useful if you want to render ordinals
0
+ # besides your records: simply start with offset + 1.
0
+ #
0
+ def offset
0
+ (current_page - 1) * per_page
0
+ end
0
+
0
+ # current_page - 1 or nil if there is no previous page
0
+ def previous_page
0
+ current_page > 1 ? (current_page - 1) : nil
0
+ end
0
+
0
+ # current_page + 1 or nil if there is no next page
0
+ def next_page
0
+ current_page < page_count ? (current_page + 1) : nil
0
+ end
0
+
0
+ def total_entries=(number)
0
+ @total_entries = number.to_i
0
+ @total_pages = (@total_entries / per_page.to_f).ceil
0
+ end
0
+
0
+ # This is a magic wrapper for the original Array#replace method. It serves
0
+ # for populating the paginated collection after initialization.
0
+ #
0
+ # Why magic? Because it tries to guess the total number of entries judging
0
+ # by the size of given array. If it is shorter than +per_page+ limit, then we
0
+ # know we're on the last page. This trick is very useful for avoiding
0
+ # unnecessary hits to the database to do the counting after we fetched the
0
+ # data for the current page.
0
+ #
0
+ # However, after using +replace+ you should always test the value of
0
+ # +total_entries+ and set it to a proper value if it's +nil+. See the example
0
+ # in +create+.
0
+ def replace(array)
0
+ returning super do
0
+ # The collection is shorter then page limit? Rejoice, because
0
+ # then we know that we are on the last page!
0
+ if total_entries.nil? and length > 0 and length < per_page
0
+ self.total_entries = offset + length
0
+ end
0
+ end
0
+ end
0
+ end
0
+end
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
0
@@ -0,0 +1,80 @@
0
+require 'will_paginate'
0
+require 'set'
0
+
0
+unless Hash.instance_methods.include? 'except'
0
+ Hash.class_eval do
0
+ # Returns a new hash without the given keys.
0
+ def except(*keys)
0
+ rejected = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
0
+ reject { |key,| rejected.include?(key) }
0
+ end
0
+
0
+ # Replaces the hash without only the given keys.
0
+ def except!(*keys)
0
+ replace(except(*keys))
0
+ end
0
+ end
0
+end
0
+
0
+unless Hash.instance_methods.include? 'slice'
0
+ Hash.class_eval do
0
+ # Returns a new hash with only the given keys.
0
+ def slice(*keys)
0
+ allowed = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
0
+ reject { |key,| !allowed.include?(key) }
0
+ end
0
+
0
+ # Replaces the hash with only the given keys.
0
+ def slice!(*keys)
0
+ replace(slice(*keys))
0
+ end
0
+ end
0
+end
0
+
0
+unless Hash.instance_methods.include? 'rec_merge!'
0
+ Hash.class_eval do
0
+ # Same as Hash#merge!, but recursively merges sub-hashes
0
+ # (stolen from Haml)
0
+ def rec_merge!(other)
0
+ other.each do |key, other_value|
0
+ value = self[key]
0
+ if value.is_a?(Hash) and other_value.is_a?(Hash)
0
+ value.rec_merge! other_value
0
+ else
0
+ self[key] = other_value
0
+ end
0
+ end
0
+ self
0
+ end
0
+ end
0
+end
0
+
0
+require 'will_paginate/collection'
0
+
0
+unless Array.instance_methods.include? 'paginate'
0
+ # http://www.desimcadam.com/archives/8
0
+ Array.class_eval do
0
+ def paginate(options_or_page = {}, per_page = nil)
0
+ if options_or_page.nil? or Fixnum === options_or_page
0
+ if defined? WillPaginate::Deprecation
0
+ WillPaginate::Deprecation.warn <<-DEPR
0
+ Array#paginate now conforms to the main, ActiveRecord::Base#paginate API. You should \
0
+ call it with a parameters hash (:page, :per_page). The old API (numbers as arguments) \
0
+ has been deprecated and is going to be unsupported in future versions of will_paginate.
0
+ DEPR
0
+ end
0
+ page = options_or_page
0
+ options = {}
0
+ else
0
+ options = options_or_page
0
+ page = options[:page]
0
+ raise ArgumentError, "wrong number of arguments (1 hash or 2 Fixnums expected)" if per_page
0
+ per_page = options[:per_page]
0
+ end
0
+
0
+ WillPaginate::Collection.create(page || 1, per_page || 30, options[:total_entries] || size) do |pager|
0
+ pager.replace self[pager.offset, pager.per_page].to_a
0
+ end
0
+ end
0
+ end
0
+end
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
0
@@ -0,0 +1,181 @@
0
+require 'will_paginate/core_ext'
0
+
0
+module WillPaginate
0
+ # A mixin for ActiveRecord::Base. Provides +per_page+ class method
0
+ # and makes +paginate+ finders possible with some method_missing magic.
0
+ #
0
+ # Find out more in WillPaginate::Finder::ClassMethods
0
+ #
0
+ module Finder
0
+ def self.included(base)
0
+ base.extend ClassMethods
0
+ class << base
0
+ alias_method_chain :method_missing, :paginate
0
+ define_method(:per_page) { 30 } unless respond_to?(:per_page)
0
+ end
0
+ end
0
+
0
+ # = Paginating finders for ActiveRecord models
0
+ #
0
+ # WillPaginate doesn't really add extra methods to your ActiveRecord models
0
+ # (except +per_page+ unless it's already available). It simply intercepts
0
+ # the calls to paginating finders such as +paginate+, +paginate_by_user_id+
0
+ # (and so on) and translates them to ordinary finders: +find+,
0
+ # +find_by_user_id+, etc. It does so with some +method_missing+ magic, but
0
+ # you don't need to care for that. You simply use paginating finders same
0
+ # way you used ordinary ones. You only need to specify what page do you want:
0
+ #
0
+ # @posts = Post.paginate :page => params[:page]
0
+ #
0
+ # In paginating finders, "all" is implicit. No sense in paginating a single
0
+ # record, right? So:
0
+ #
0
+ # Post.paginate => Post.find :all
0
+ # Post.paginate_all_by_something => Post.find_all_by_something
0
+ # Post.paginate_by_something => Post.find_all_by_something
0
+ #
0
+ # Don't forget to pass the +page+ parameter! Without it, paginating finders
0
+ # will raise an error.
0
+ #
0
+ # == Options for paginating finders
0
+ # * <tt>:page</tt> -- REQUIRED, but defaults to 1 if false or nil
0
+ # * <tt>:per_page</tt> -- defaults to <tt>CurrentModel.per_page</tt> (which is 30 if not overridden)
0
+ # * <tt>:total_entries</tt> -- use only if you manually count total entries
0
+ # * <tt>:count</tt> -- additional options that are passed on to +count+
0
+ #
0
+ module ClassMethods
0
+ # This methods wraps +find_by_sql+ by simply adding LIMIT and OFFSET to your SQL string
0
+ # based on the params otherwise used by paginating finds: +page+ and +per_page+.
0
+ #
0
+ # Example:
0
+ #
0
+ # @developers = Developer.paginate_by_sql ['select * from developers where salary > ?', 80000],
0
+ # :page => params[:page], :per_page => 3
0
+ #
0
+ # A query for counting rows will automatically be generated if you don't
0
+ # supply <tt>:total_entries</tt>. If you experience problems with this
0
+ # generated SQL, you might want to perform the count manually in your
0
+ # application.
0
+ #
0
+ def paginate_by_sql(sql, options)
0
+ WillPaginate::Collection.create(*wp_parse_options!(options)) do |pager|
0
+ query = sanitize_sql(sql)
0
+ options.update :offset => pager.offset, :limit => pager.per_page
0
+
0
+ original_query = query.dup
0
+ add_limit! query, options
0
+ # perfom the find
0
+ pager.replace find_by_sql(query)
0
+
0
+ unless pager.total_entries
0
+ count_query = original_query.sub /\bORDER\s+BY\s+[\w`,\s]+$/mi, ''
0
+ count_query = "SELECT COUNT(*) FROM (#{count_query}) AS count_table"
0
+ # perform the count query
0
+ pager.total_entries = count_by_sql(count_query)
0
+ end
0
+ end
0
+ end
0
+
0
+ def respond_to?(method, include_priv = false)
0
+ case method.to_sym
0
+ when :paginate, :paginate_by_sql
0
+ true
0
+ else
0
+ super(method.to_s.sub(/^paginate/, 'find'), include_priv)
0
+ end
0
+ end
0
+
0
+ protected
0
+
0
+ def method_missing_with_paginate(method, *args, &block)
0
+ # did somebody tried to paginate? if not, let them be
0
+ unless method.to_s.index('paginate') == 0
0
+ return method_missing_without_paginate(method, *args, &block)
0
+ end
0
+
0
+ options = args.pop
0
+ page, per_page, total_entries = wp_parse_options!(options)
0
+ # an array of IDs may have been given:
0
+ total_entries ||= (Array === args.first and args.first.size)
0
+
0
+ # paginate finders are really just find_* with limit and offset
0
+ finder = method.to_s.sub /^paginate/, 'find'
0
+
0
+ # :all is implicit
0
+ if finder == 'find'
0
+ args.unshift(:all) if args.empty?
0
+ elsif finder.index('find_by_') == 0
0
+ finder.sub! /^find/, 'find_all'
0
+ end
0
+
0
+ WillPaginate::Collection.create(page, per_page, total_entries) do |pager|
0
+ args << options.except(:count).merge(:offset => pager.offset, :limit => pager.per_page)
0
+ pager.replace send(finder, *args)
0
+
0
+ # magic counting for user convenience:
0
+ pager.total_entries = wp_count!(options, args, finder) unless pager.total_entries
0
+ end
0
+ end
0
+
0
+ def wp_count!(options, args, finder)
0
+ excludees = [:count, :order, :limit, :offset]
0
+ unless options[:select] and options[:select] =~ /^\s*DISTINCT/i
0
+ excludees << :select # only exclude the select param if it doesn't begin with DISTINCT
0
+ end
0
+ # count expects (almost) the same options as find
0
+ count_options = options.except *excludees
0
+
0
+ # merge the hash found in :count
0
+ # this allows you to specify :select, :order, or anything else just for the count query
0
+ count_options.update(options.delete(:count) || {}) if options.key? :count
0
+
0
+ # we may have to scope ...
0
+ counter = Proc.new { count(count_options) }
0
+
0
+ # we may be in a model or an association proxy!
0
+ klass = (@owner and @reflection) ? @reflection.klass : self
0
+
0
+ count = if finder =~ /^find_/ and klass.respond_to?(scoper = finder.sub(/^find_/, 'with_'))
0
+ # scope_out adds a 'with_finder' method which acts like with_scope, if it's present
0
+ # then execute the count with the scoping provided by the with_finder
0
+ send(scoper, &counter)
0
+ elsif conditions = wp_extract_finder_conditions(finder, args)
0
+ # extracted the conditions from calls like "paginate_by_foo_and_bar"
0
+ with_scope(:find => { :conditions => conditions }, &counter)
0
+ else
0
+ counter.call
0
+ end
0
+
0
+ count.respond_to?(:length) ? count.length : count
0
+ end
0
+
0
+ def wp_parse_options!(options)
0
+ raise ArgumentError, 'hash parameters expected' unless options.respond_to? :symbolize_keys!
0
+ options.symbolize_keys!
0
+ raise ArgumentError, ':page parameter required' unless options.key? :page
0
+
0
+ if options[:count] and options[:total_entries]
0
+ raise ArgumentError, ':count and :total_entries are mutually exclusive parameters'
0
+ end
0
+
0
+ page = options.delete(:page) || 1
0
+ per_page = options.delete(:per_page) || self.per_page
0
+ total = options.delete(:total_entries)
0
+ [page, per_page, total]
0
+ end
0
+
0
+ private
0
+
0
+ # thanks to active record for making us duplicate this code
0
+ def wp_extract_finder_conditions(finder, arguments)
0
+ return unless match = /^find_(all_by|by)_([_a-zA-Z]\w*)$/.match(finder.to_s)
0
+
0
+ attribute_names = extract_attribute_names_from_match(match)
0
+ unless all_attributes_exists?(attribute_names)
0
+ raise "I can't make sense of `#{finder}`. Try doing the count manually"
0
+ end
0
+ construct_attributes_from_arguments(attribute_names, arguments)
0
+ end
0
+ end
0
+ end
0
+end
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
0
@@ -0,0 +1,206 @@
0
+require 'will_paginate/core_ext'
0
+
0
+module WillPaginate
0
+ # = Will Paginate view helpers
0
+ #
0
+ # Currently there is only one view helper: +will_paginate+. It renders the
0
+ # pagination links for the given collection. The helper itself is lightweight
0
+ # and serves only as a wrapper around link renderer instantiation; the
0
+ # renderer then does all the hard work of generating the HTML.
0
+ #
0
+ # == Global options for helpers
0
+ #
0
+ # Options for pagination helpers are optional and get their default values from the
0
+ # WillPaginate::ViewHelpers.pagination_options hash. You can write to this hash to
0
+ # override default options on the global level:
0
+ #
0
+ # WillPaginate::ViewHelpers.pagination_options[:prev_label] = 'Previous page'
0
+ #
0
+ # By putting this into your environment.rb you can easily translate link texts to previous
0
+ # and next pages, as well as override some other defaults to your liking.
0
+ module ViewHelpers
0
+ # default options that can be overridden on the global level
0
+ @@pagination_options = {
0
+ :class => 'pagination',
0
+ :prev_label => '&laquo; Previous',
0
+ :next_label => 'Next &raquo;',
0
+ :inner_window => 4, # links around the current page
0
+ :outer_window => 1, # links around beginning and end
0
+ :separator => ' ', # single space is friendly to spiders and non-graphic browsers
0
+ :param_name => :page,
0
+ :params => nil,
0
+ :renderer => 'WillPaginate::LinkRenderer',
0
+ :page_links => true,
0
+ :container => true
0
+ }
0
+ mattr_reader :pagination_options
0
+
0
+ # Renders Digg/Flickr-style pagination for a WillPaginate::Collection
0
+ # object. Nil is returned if there is only one page in total; no point in
0
+ # rendering the pagination in that case...
0
+ #
0
+ # ==== Options
0
+ # * <tt>:class</tt> -- CSS class name for the generated DIV (default: "pagination")
0
+ # * <tt>:prev_label</tt> -- default: "« Previous"
0
+ # * <tt>:next_label</tt> -- default: "Next »"
0
+ # * <tt>:inner_window</tt> -- how many links are shown around the current page (default: 4)
0
+ # * <tt>:outer_window</tt> -- how many links are around the first and the last page (default: 1)
0
+ # * <tt>:separator</tt> -- string separator for page HTML elements (default: single space)
0
+ # * <tt>:param_name</tt> -- parameter name for page number in URLs (default: <tt>:page</tt>)
0
+ # * <tt>:params</tt> -- additional parameters when generating pagination links
0
+ # (eg. <tt>:controller => "foo", :action => nil</tt>)
0
+ # * <tt>:renderer</tt> -- class name of the link renderer (default: WillPaginate::LinkRenderer)
0
+ # * <tt>:page_links</tt> -- when false, only previous/next links are rendered (default: true)
0
+ # * <tt>:container</tt> -- toggles rendering of the DIV container for pagination links, set to
0
+ # false only when you are rendering your own pagination markup (default: true)
0
+ # * <tt>:id</tt> -- HTML ID for the container (default: nil). Pass +true+ to have the ID automatically
0
+ # generated from the class name of objects in collection: for example, paginating
0
+ # ArticleComment models would yield an ID of "article_comments_pagination".
0
+ #
0
+ # All options beside listed ones are passed as HTML attributes to the container
0
+ # element for pagination links (the DIV). For example:
0
+ #
0
+ # <%= will_paginate @posts, :id => 'wp_posts' %>
0
+ #
0
+ # ... will result in:
0
+ #
0
+ # <div class="pagination" id="wp_posts"> ... </div>
0
+ #
0
+ # ==== Using the helper without arguments
0
+ # If the helper is called without passing in the collection object, it will
0
+ # try to read from the instance variable inferred by the controller name.
0
+ # For example, calling +will_paginate+ while the current controller is
0
+ # PostsController will result in trying to read from the <tt>@posts</tt>
0
+ # variable. Example:
0
+ #
0
+ # <%= will_paginate :id => true %>
0
+ #
0
+ # ... will result in <tt>@post</tt> collection getting paginated:
0
+ #
0
+ # <div class="pagination" id="posts_pagination"> ... </div>
0
+ #
0
+ def will_paginate(collection = nil, options = {})