Module | Cms::Behaviors::Pagination::ClassMethods |
In: |
lib/cms/behaviors/pagination.rb
|
This is the main paginating finder.
All other options (conditions, order, …) are forwarded to find and count calls.
# File lib/cms/behaviors/pagination.rb, line 131 131: def paginate(*args, &block) 132: options = args.pop 133: page, per_page, total_entries = parse_pagination_options(options) 134: 135: finder = (options[:finder] || 'find').to_s 136: if finder == 'find' 137: # an array of IDs may have been given: 138: total_entries ||= (Array === args.first and args.first.size) 139: # :all is implicit 140: args.unshift(:all) if args.empty? 141: end 142: 143: Collection.create(page, per_page, total_entries) do |pager| 144: count_options = options.except :page, :per_page, :total_entries, :finder 145: find_options = count_options.except(:count).update(:offset => pager.offset, :limit => pager.per_page) 146: 147: args << find_options 148: # @options_from_last_find = nil 149: pager.replace send(finder, *args, &block) 150: 151: # magic counting for user convenience: 152: pager.total_entries = count_for_pagination(count_options, args, finder) unless pager.total_entries 153: end 154: end
Does the not-so-trivial job of finding out the total number of entries in the database. It relies on the ActiveRecord count method.
# File lib/cms/behaviors/pagination.rb, line 158 158: def count_for_pagination(options, args, finder) 159: excludees = [:count, :order, :limit, :offset, :readonly] 160: unless options[:select] and options[:select] =~ /^\s*DISTINCT\b/i 161: excludees << :select # only exclude the select param if it doesn't begin with DISTINCT 162: end 163: # count expects (almost) the same options as find 164: count_options = options.except *excludees 165: 166: # merge the hash found in :count 167: # this allows you to specify :select, :order, or anything else just for the count query 168: count_options.update options[:count] if options[:count] 169: 170: # we may have to scope ... 171: counter = Proc.new { count(count_options) } 172: 173: # we may be in a model or an association proxy! 174: klass = (@owner and @reflection) ? @reflection.klass : self 175: 176: count = if finder.index('find_') == 0 and klass.respond_to?(scoper = finder.sub('find', 'with')) 177: # scope_out adds a 'with_finder' method which acts like with_scope, if it's present 178: # then execute the count with the scoping provided by the with_finder 179: send(scoper, &counter) 180: elsif match = /^find_(all_by|by)_([_a-zA-Z]\w*)$/.match(finder) 181: # extract conditions from calls like "paginate_by_foo_and_bar" 182: attribute_names = extract_attribute_names_from_match(match) 183: conditions = construct_attributes_from_arguments(attribute_names, args) 184: with_scope(:find => { :conditions => conditions }, &counter) 185: else 186: counter.call 187: end 188: 189: count.respond_to?(:length) ? count.length : count 190: end