Skip to content
Browse files

implemented simple pagination

  • Loading branch information...
1 parent 39654d3 commit 35dc3c303607b3ae30ed6a43d7edb30e48e6338b @aboutaaron committed Feb 27, 2013
Showing with 3,868 additions and 3 deletions.
  1. +1 −0 Gemfile
  2. +2 −0 Gemfile.lock
  3. +1 −1 app/controllers/tweets_controller.rb
  4. +3 −2 app/views/tweets/index.html.erb
  5. +1 −0 vendor/bundle/build_info/will_paginate-3.0.4.info
  6. BIN vendor/bundle/cache/will_paginate-3.0.4.gem
  7. +18 −0 vendor/bundle/gems/will_paginate-3.0.4/LICENSE
  8. +61 −0 vendor/bundle/gems/will_paginate-3.0.4/README.md
  9. +25 −0 vendor/bundle/gems/will_paginate-3.0.4/Rakefile
  10. +25 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate.rb
  11. +247 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/active_record.rb
  12. +33 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/array.rb
  13. +136 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/collection.rb
  14. +30 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/core_ext.rb
  15. +95 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/data_mapper.rb
  16. +55 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/deprecation.rb
  17. +22 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/i18n.rb
  18. +33 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/locale/en.yml
  19. +57 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/page_number.rb
  20. +27 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/per_page.rb
  21. +68 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/railtie.rb
  22. +39 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/sequel.rb
  23. +9 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/version.rb
  24. +160 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/view_helpers.rb
  25. +148 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/view_helpers/action_view.rb
  26. +131 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/view_helpers/link_renderer.rb
  27. +77 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/view_helpers/link_renderer_base.rb
  28. +26 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/view_helpers/merb.rb
  29. +41 −0 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/view_helpers/sinatra.rb
  30. +29 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/ci.rb
  31. +139 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/collection_spec.rb
  32. +12 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/console
  33. +28 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/console_fixtures.rb
  34. +22 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/database.yml
  35. +556 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/finders/active_record_spec.rb
  36. +115 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/finders/activerecord_test_connector.rb
  37. +103 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/finders/data_mapper_spec.rb
  38. +54 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/finders/data_mapper_test_connector.rb
  39. +67 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/finders/sequel_spec.rb
  40. +15 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/finders/sequel_test_connector.rb
  41. +3 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/fixtures/admin.rb
  42. +13 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/fixtures/developer.rb
  43. +13 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/fixtures/developers_projects.yml
  44. +15 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/fixtures/project.rb
  45. +6 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/fixtures/projects.yml
  46. +29 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/fixtures/replies.yml
  47. +9 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/fixtures/reply.rb
  48. +38 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/fixtures/schema.rb
  49. +7 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/fixtures/topic.rb
  50. +30 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/fixtures/topics.yml
  51. +2 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/fixtures/user.rb
  52. +35 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/fixtures/users.yml
  53. +65 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/page_number_spec.rb
  54. +41 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/per_page_spec.rb
  55. +71 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/spec_helper.rb
  56. +423 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/view_helpers/action_view_spec.rb
  57. +130 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/view_helpers/base_spec.rb
  58. +87 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/view_helpers/link_renderer_base_spec.rb
  59. +121 −0 vendor/bundle/gems/will_paginate-3.0.4/spec/view_helpers/view_example_group.rb
  60. +19 −0 vendor/bundle/specifications/will_paginate-3.0.4.gemspec
View
1 Gemfile
@@ -9,6 +9,7 @@ gem 'sqlite3'
gem 'simple_form'
gem 'twitter'
gem 'twitter-text'
+gem 'will_paginate', '~> 3.0'
# Gems used only for assets and not required
# in production environments by default.
View
2 Gemfile.lock
@@ -119,6 +119,7 @@ GEM
uglifier (1.3.0)
execjs (>= 0.3.0)
multi_json (~> 1.0, >= 1.0.2)
+ will_paginate (3.0.4)
PLATFORMS
ruby
@@ -136,3 +137,4 @@ DEPENDENCIES
twitter
twitter-text
uglifier (>= 1.0.3)
+ will_paginate (~> 3.0)
View
2 app/controllers/tweets_controller.rb
@@ -1,6 +1,6 @@
class TweetsController < ApplicationController
def index
- @tweets = Tweet.all
+ @tweets = Tweet.paginate(:page => params[:page], :per_page => 10)
end
def new
View
5 app/views/tweets/index.html.erb
@@ -1,10 +1,11 @@
<div class="span6 offset3">
<ul class="unstyled">
- <% @tweets.reverse.each do |tweet| %>
+ <% @tweets.each do |tweet| %>
<li>
- <span id="user"><%= hyperlink_the_tings("@#{tweet.user}") %></span> <span id="content"><%= hyperlink_the_tings(tweet.content) %></span> (<span id="tweet-id"><%= tweet.tweet_id %></span>)</li>
+ <span id="user"><%= hyperlink_the_tings("@#{tweet.user}") %></span> <span id="content"><%= hyperlink_the_tings(tweet.content) + " (#{tweet.id})" %></span> (<span id="tweet-id"><%= tweet.tweet_id %></span>)</li>
<% end %>
</ul>
+ <%= will_paginate @tweets %>
<%= link_to 'Fetch a new tweet!', new_tweet_path %>
</div>
View
1 vendor/bundle/build_info/will_paginate-3.0.4.info
@@ -0,0 +1 @@
+
View
BIN vendor/bundle/cache/will_paginate-3.0.4.gem
Binary file not shown.
View
18 vendor/bundle/gems/will_paginate-3.0.4/LICENSE
@@ -0,0 +1,18 @@
+Copyright (c) 2009 Mislav Marohnić
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
61 vendor/bundle/gems/will_paginate-3.0.4/README.md
@@ -0,0 +1,61 @@
+# will_paginate
+
+will_paginate is a pagination library that integrates with Ruby on Rails, Sinatra, Merb, DataMapper and Sequel.
+
+Installation:
+
+``` ruby
+## Gemfile for Rails 3, Sinatra, and Merb
+gem 'will_paginate', '~> 3.0'
+```
+
+See [installation instructions][install] on the wiki for more info.
+
+
+## Basic will_paginate use
+
+``` ruby
+## perform a paginated query:
+@posts = Post.paginate(:page => params[:page])
+
+# or, use an explicit "per page" limit:
+Post.paginate(:page => params[:page], :per_page => 30)
+
+## render page links in the view:
+<%= will_paginate @posts %>
+```
+
+And that's it! You're done. You just need to add some CSS styles to [make those pagination links prettier][css].
+
+You can customize the default "per_page" value:
+
+``` ruby
+# for the Post model
+class Post
+ self.per_page = 10
+end
+
+# set per_page globally
+WillPaginate.per_page = 10
+```
+
+New in Active Record 3:
+
+``` ruby
+# paginate in Active Record now returns a Relation
+Post.where(:published => true).paginate(:page => params[:page]).order('id DESC')
+
+# the new, shorter page() method
+Post.page(params[:page]).order('created_at DESC')
+```
+
+See [the wiki][wiki] for more documentation. [Ask on the group][group] if you have usage questions. [Report bugs][issues] on GitHub.
+
+Happy paginating.
+
+
+[wiki]: https://github.com/mislav/will_paginate/wiki
+[install]: https://github.com/mislav/will_paginate/wiki/Installation "will_paginate installation"
+[group]: http://groups.google.com/group/will_paginate "will_paginate discussion and support group"
+[issues]: https://github.com/mislav/will_paginate/issues
+[css]: http://mislav.uniqpath.com/will_paginate/
View
25 vendor/bundle/gems/will_paginate-3.0.4/Rakefile
@@ -0,0 +1,25 @@
+begin
+ require 'rspec/core/rake_task'
+rescue LoadError
+ # no spec tasks
+else
+ task :default => :spec
+
+ desc 'Run ALL OF the specs'
+ RSpec::Core::RakeTask.new(:spec) do |t|
+ # t.ruby_opts = '-w'
+ t.pattern = 'spec/finders/active_record_spec.rb' if ENV['DB'] and ENV['DB'] != 'sqlite3'
+ end
+
+ namespace :spec do
+ desc "Run Rails specs"
+ RSpec::Core::RakeTask.new(:rails) do |t|
+ t.pattern = %w'spec/finders/active_record_spec.rb spec/view_helpers/action_view_spec.rb'
+ end
+ end
+end
+
+desc 'Run specs against both Rails 3.1 and Rails 3.0'
+task :rails3 do |variable|
+ system 'bundle exec rake spec && BUNDLE_GEMFILE=Gemfile.rails3.0 bundle exec rake spec:rails'
+end
View
25 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate.rb
@@ -0,0 +1,25 @@
+# You will paginate!
+module WillPaginate
+end
+
+if defined?(Rails::Railtie)
+ require 'will_paginate/railtie'
+elsif defined?(Rails::Initializer)
+ raise "will_paginate 3.0 is not compatible with Rails 2.3 or older"
+end
+
+if defined?(Merb::AbstractController)
+ require 'will_paginate/view_helpers/merb'
+
+ Merb::BootLoader.before_app_loads do
+ adapters = { :datamapper => 'data_mapper', :activerecord => 'active_record', :sequel => 'sequel' }
+ # auto-load the right ORM adapter
+ if adapter = adapters[Merb.orm]
+ require "will_paginate/#{adapter}"
+ end
+ end
+end
+
+if defined?(Sinatra) and Sinatra.respond_to? :register
+ require 'will_paginate/view_helpers/sinatra'
+end
View
247 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/active_record.rb
@@ -0,0 +1,247 @@
+require 'will_paginate/per_page'
+require 'will_paginate/page_number'
+require 'will_paginate/collection'
+require 'active_record'
+
+module WillPaginate
+ # = Paginating finders for ActiveRecord models
+ #
+ # WillPaginate adds +paginate+, +per_page+ and other methods to
+ # ActiveRecord::Base class methods and associations.
+ #
+ # In short, paginating finders are equivalent to ActiveRecord finders; the
+ # only difference is that we start with "paginate" instead of "find" and
+ # that <tt>:page</tt> is required parameter:
+ #
+ # @posts = Post.paginate :all, :page => params[:page], :order => 'created_at DESC'
+ #
+ module ActiveRecord
+ # makes a Relation look like WillPaginate::Collection
+ module RelationMethods
+ include WillPaginate::CollectionMethods
+
+ attr_accessor :current_page
+ attr_writer :total_entries, :wp_count_options
+
+ def per_page(value = nil)
+ if value.nil? then limit_value
+ else limit(value)
+ end
+ end
+
+ # TODO: solve with less relation clones and code dups
+ def limit(num)
+ rel = super
+ if rel.current_page
+ rel.offset rel.current_page.to_offset(rel.limit_value).to_i
+ else
+ rel
+ end
+ end
+
+ # dirty hack to enable `first` after `limit` behavior above
+ def first(*args)
+ if current_page
+ rel = clone
+ rel.current_page = nil
+ rel.first(*args)
+ else
+ super
+ end
+ end
+
+ # fix for Rails 3.0
+ def find_last
+ if !loaded? and offset_value || limit_value
+ @last ||= to_a.last
+ else
+ super
+ end
+ end
+
+ def offset(value = nil)
+ if value.nil? then offset_value
+ else super(value)
+ end
+ end
+
+ def total_entries
+ @total_entries ||= begin
+ if loaded? and size < limit_value and (current_page == 1 or size > 0)
+ offset_value + size
+ else
+ @total_entries_queried = true
+ result = count
+ result = result.size if result.respond_to?(:size) and !result.is_a?(Integer)
+ result
+ end
+ end
+ end
+
+ def count
+ if limit_value
+ excluded = [:order, :limit, :offset]
+ excluded << :includes unless eager_loading?
+ rel = self.except(*excluded)
+ # TODO: hack. decide whether to keep
+ rel = rel.apply_finder_options(@wp_count_options) if defined? @wp_count_options
+ rel.count
+ else
+ super
+ end
+ end
+
+ # workaround for Active Record 3.0
+ def size
+ if !loaded? and limit_value and group_values.empty?
+ [super, limit_value].min
+ else
+ super
+ end
+ end
+
+ # overloaded to be pagination-aware
+ def empty?
+ if !loaded? and offset_value
+ result = count
+ result = result.size if result.respond_to?(:size) and !result.is_a?(Integer)
+ result <= offset_value
+ else
+ super
+ end
+ end
+
+ def clone
+ copy_will_paginate_data super
+ end
+
+ # workaround for Active Record 3.0
+ def scoped(options = nil)
+ copy_will_paginate_data super
+ end
+
+ def to_a
+ if current_page.nil? then super # workaround for Active Record 3.0
+ else
+ ::WillPaginate::Collection.create(current_page, limit_value) do |col|
+ col.replace super
+ col.total_entries ||= total_entries
+ end
+ end
+ end
+
+ private
+
+ def copy_will_paginate_data(other)
+ other.current_page = current_page unless other.current_page
+ other.total_entries = nil if defined? @total_entries_queried
+ other.wp_count_options = @wp_count_options if defined? @wp_count_options
+ other
+ end
+ end
+
+ module Pagination
+ def paginate(options)
+ options = options.dup
+ pagenum = options.fetch(:page) { raise ArgumentError, ":page parameter required" }
+ per_page = options.delete(:per_page) || self.per_page
+ total = options.delete(:total_entries)
+
+ count_options = options.delete(:count)
+ options.delete(:page)
+
+ rel = limit(per_page.to_i).page(pagenum)
+ rel = rel.apply_finder_options(options) if options.any?
+ rel.wp_count_options = count_options if count_options
+ rel.total_entries = total.to_i unless total.blank?
+ rel
+ end
+
+ def page(num)
+ rel = if ::ActiveRecord::Relation === self
+ self
+ elsif !defined?(::ActiveRecord::Scoping) or ::ActiveRecord::Scoping::ClassMethods.method_defined? :with_scope
+ # Active Record 3
+ scoped
+ else
+ # Active Record 4
+ all
+ end
+
+ rel = rel.extending(RelationMethods)
+ pagenum = ::WillPaginate::PageNumber(num.nil? ? 1 : num)
+ per_page = rel.limit_value || self.per_page
+ rel = rel.offset(pagenum.to_offset(per_page).to_i)
+ rel = rel.limit(per_page) unless rel.limit_value
+ rel.current_page = pagenum
+ rel
+ end
+ end
+
+ module BaseMethods
+ # Wraps +find_by_sql+ by simply adding LIMIT and OFFSET to your SQL string
+ # based on the params otherwise used by paginating finds: +page+ and
+ # +per_page+.
+ #
+ # Example:
+ #
+ # @developers = Developer.paginate_by_sql ['select * from developers where salary > ?', 80000],
+ # :page => params[:page], :per_page => 3
+ #
+ # A query for counting rows will automatically be generated if you don't
+ # supply <tt>:total_entries</tt>. If you experience problems with this
+ # generated SQL, you might want to perform the count manually in your
+ # application.
+ #
+ def paginate_by_sql(sql, options)
+ pagenum = options.fetch(:page) { raise ArgumentError, ":page parameter required" } || 1
+ per_page = options[:per_page] || self.per_page
+ total = options[:total_entries]
+
+ WillPaginate::Collection.create(pagenum, per_page, total) do |pager|
+ query = sanitize_sql(sql.dup)
+ original_query = query.dup
+ oracle = self.connection.adapter_name =~ /^(oracle|oci$)/i
+
+ # add limit, offset
+ if oracle
+ query = <<-SQL
+ SELECT * FROM (
+ SELECT rownum rnum, a.* FROM (#{query}) a
+ WHERE rownum <= #{pager.offset + pager.per_page}
+ ) WHERE rnum >= #{pager.offset}
+ SQL
+ else
+ query << " LIMIT #{pager.per_page} OFFSET #{pager.offset}"
+ end
+
+ # perfom the find
+ pager.replace find_by_sql(query)
+
+ unless pager.total_entries
+ count_query = original_query.sub /\bORDER\s+BY\s+[\w`,\s.]+$/mi, ''
+ count_query = "SELECT COUNT(*) FROM (#{count_query})"
+ count_query << ' AS count_table' unless oracle
+ # perform the count query
+ pager.total_entries = count_by_sql(count_query)
+ end
+ end
+ end
+ end
+
+ # mix everything into Active Record
+ ::ActiveRecord::Base.extend PerPage
+ ::ActiveRecord::Base.extend Pagination
+ ::ActiveRecord::Base.extend BaseMethods
+
+ klasses = [::ActiveRecord::Relation]
+ if defined? ::ActiveRecord::Associations::CollectionProxy
+ klasses << ::ActiveRecord::Associations::CollectionProxy
+ else
+ klasses << ::ActiveRecord::Associations::AssociationCollection
+ end
+
+ # support pagination on associations and scopes
+ klasses.each { |klass| klass.send(:include, Pagination) }
+ end
+end
View
33 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/array.rb
@@ -0,0 +1,33 @@
+require 'will_paginate/collection'
+
+class Array
+ # Paginates a static array (extracting a subset of it). The result is a
+ # WillPaginate::Collection instance, which is an array with a few more
+ # properties about its paginated state.
+ #
+ # Parameters:
+ # * <tt>:page</tt> - current page, defaults to 1
+ # * <tt>:per_page</tt> - limit of items per page, defaults to 30
+ # * <tt>:total_entries</tt> - total number of items in the array, defaults to
+ # <tt>array.length</tt> (obviously)
+ #
+ # Example:
+ # arr = ['a', 'b', 'c', 'd', 'e']
+ # paged = arr.paginate(:per_page => 2) #-> ['a', 'b']
+ # paged.total_entries #-> 5
+ # arr.paginate(:page => 2, :per_page => 2) #-> ['c', 'd']
+ # arr.paginate(:page => 3, :per_page => 2) #-> ['e']
+ #
+ # This method was originally {suggested by Desi
+ # McAdam}[http://www.desimcadam.com/archives/8] and later proved to be the
+ # most useful method of will_paginate library.
+ def paginate(options = {})
+ page = options[:page] || 1
+ per_page = options[:per_page] || WillPaginate.per_page
+ total = options[:total_entries] || self.length
+
+ WillPaginate::Collection.create(page, per_page, total) do |pager|
+ pager.replace self[pager.offset, pager.per_page].to_a
+ end
+ end
+end
View
136 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/collection.rb
@@ -0,0 +1,136 @@
+require 'will_paginate/per_page'
+require 'will_paginate/page_number'
+
+module WillPaginate
+ # Any will_paginate-compatible collection should have these methods:
+ #
+ # current_page, per_page, offset, total_entries, total_pages
+ #
+ # It can also define some of these optional methods:
+ #
+ # out_of_bounds?, previous_page, next_page
+ #
+ # This module provides few of these methods.
+ module CollectionMethods
+ def total_pages
+ total_entries.zero? ? 1 : (total_entries / per_page.to_f).ceil
+ end
+
+ # current_page - 1 or nil if there is no previous page
+ def previous_page
+ current_page > 1 ? (current_page - 1) : nil
+ end
+
+ # current_page + 1 or nil if there is no next page
+ def next_page
+ current_page < total_pages ? (current_page + 1) : nil
+ end
+
+ # Helper method that is true when someone tries to fetch a page with a
+ # larger number than the last page. Can be used in combination with flashes
+ # and redirecting.
+ def out_of_bounds?
+ current_page > total_pages
+ end
+ end
+
+ # = The key to pagination
+ # Arrays returned from paginating finds are, in fact, instances of this little
+ # class. You may think of WillPaginate::Collection as an ordinary array with
+ # some extra properties. Those properties are used by view helpers to generate
+ # correct page links.
+ #
+ # WillPaginate::Collection also assists in rolling out your own pagination
+ # solutions: see +create+.
+ #
+ # If you are writing a library that provides a collection which you would like
+ # to conform to this API, you don't have to copy these methods over; simply
+ # make your plugin/gem dependant on this library and do:
+ #
+ # require 'will_paginate/collection'
+ # # WillPaginate::Collection is now available for use
+ class Collection < Array
+ include CollectionMethods
+
+ attr_reader :current_page, :per_page, :total_entries
+
+ # Arguments to the constructor are the current page number, per-page limit
+ # and the total number of entries. The last argument is optional because it
+ # is best to do lazy counting; in other words, count *conditionally* after
+ # populating the collection using the +replace+ method.
+ def initialize(page, per_page = WillPaginate.per_page, total = nil)
+ @current_page = WillPaginate::PageNumber(page)
+ @per_page = per_page.to_i
+ self.total_entries = total if total
+ end
+
+ # Just like +new+, but yields the object after instantiation and returns it
+ # afterwards. This is very useful for manual pagination:
+ #
+ # @entries = WillPaginate::Collection.create(1, 10) do |pager|
+ # result = Post.find(:all, :limit => pager.per_page, :offset => pager.offset)
+ # # inject the result array into the paginated collection:
+ # pager.replace(result)
+ #
+ # unless pager.total_entries
+ # # the pager didn't manage to guess the total count, do it manually
+ # pager.total_entries = Post.count
+ # end
+ # end
+ #
+ # The possibilities with this are endless. For another example, here is how
+ # WillPaginate used to define pagination for Array instances:
+ #
+ # Array.class_eval do
+ # def paginate(page = 1, per_page = 15)
+ # WillPaginate::Collection.create(page, per_page, size) do |pager|
+ # pager.replace self[pager.offset, pager.per_page].to_a
+ # end
+ # end
+ # end
+ #
+ # The Array#paginate API has since then changed, but this still serves as a
+ # fine example of WillPaginate::Collection usage.
+ def self.create(page, per_page, total = nil)
+ pager = new(page, per_page, total)
+ yield pager
+ pager
+ end
+
+ # Current offset of the paginated collection. If we're on the first page,
+ # it is always 0. If we're on the 2nd page and there are 30 entries per page,
+ # the offset is 30. This property is useful if you want to render ordinals
+ # side by side with records in the view: simply start with offset + 1.
+ def offset
+ current_page.to_offset(per_page).to_i
+ end
+
+ def total_entries=(number)
+ @total_entries = number.to_i
+ end
+
+ # This is a magic wrapper for the original Array#replace method. It serves
+ # for populating the paginated collection after initialization.
+ #
+ # Why magic? Because it tries to guess the total number of entries judging
+ # by the size of given array. If it is shorter than +per_page+ limit, then we
+ # know we're on the last page. This trick is very useful for avoiding
+ # unnecessary hits to the database to do the counting after we fetched the
+ # data for the current page.
+ #
+ # However, after using +replace+ you should always test the value of
+ # +total_entries+ and set it to a proper value if it's +nil+. See the example
+ # in +create+.
+ def replace(array)
+ result = super
+
+ # The collection is shorter then page limit? Rejoice, because
+ # then we know that we are on the last page!
+ if total_entries.nil? and length < per_page and (current_page == 1 or length > 0)
+ self.total_entries = offset + length
+ end
+
+ result
+ end
+ end
+end
View
30 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/core_ext.rb
@@ -0,0 +1,30 @@
+require 'set'
+
+# copied from ActiveSupport so we don't depend on it
+
+unless Hash.method_defined? :except
+ Hash.class_eval do
+ # Returns a new hash without the given keys.
+ def except(*keys)
+ rejected = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
+ reject { |key,| rejected.include?(key) }
+ end
+
+ # Replaces the hash without only the given keys.
+ def except!(*keys)
+ replace(except(*keys))
+ end
+ end
+end
+
+unless String.method_defined? :underscore
+ String.class_eval do
+ def underscore
+ self.to_s.gsub(/::/, '/').
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
+ tr("-", "_").
+ downcase
+ end
+ end
+end
View
95 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/data_mapper.rb
@@ -0,0 +1,95 @@
+require 'dm-core'
+require 'dm-aggregates'
+require 'will_paginate/per_page'
+require 'will_paginate/page_number'
+require 'will_paginate/collection'
+
+module WillPaginate
+ module DataMapper
+ module Pagination
+ def page(num)
+ pagenum = ::WillPaginate::PageNumber(num.nil? ? 1 : num)
+ per_page = query.limit || self.per_page
+ options = {:offset => pagenum.to_offset(per_page).to_i}
+ options[:limit] = per_page unless query.limit
+ col = new_collection(query.merge(options))
+ col.current_page = pagenum
+ col
+ end
+
+ def paginate(options)
+ options = options.dup
+ pagenum = options.fetch(:page) { raise ArgumentError, ":page parameter required" }
+ per_page = options.delete(:per_page) || self.per_page
+
+ options.delete(:page)
+ options[:limit] = per_page.to_i
+
+ all(options).page(pagenum)
+ end
+ end
+
+ module CollectionMethods
+ include WillPaginate::CollectionMethods
+
+ attr_accessor :current_page
+
+ def paginated?
+ !current_page.nil?
+ end
+
+ def per_page
+ query.limit || model.per_page
+ end
+
+ def offset
+ query.offset
+ end
+
+ def total_entries
+ @total_entries ||= begin
+ if loaded? and @array.size < per_page and (current_page == 1 or @array.size > 0)
+ offset + @array.size
+ else
+ # :reload prevents Collection.filter from being run, which
+ # would cause a stack overflow
+ clean_query = query.merge(:reload => true)
+ # seems like the only way
+ clean_query.instance_variable_set('@limit', nil)
+ clean_query.instance_variable_set('@offset', 0)
+ new_collection(clean_query).count
+ end
+ end
+ end
+
+ def to_a
+ if paginated?
+ ::WillPaginate::Collection.create(current_page, per_page) do |col|
+ col.replace super
+ col.total_entries ||= total_entries
+ end
+ else
+ super
+ end
+ end
+
+ private
+
+ def new_collection(query, resources = nil)
+ col = super
+ col.current_page = self.current_page
+ col
+ end
+
+ def initialize_copy(original)
+ super
+ @total_entries = nil
+ end
+ end
+
+ ::DataMapper::Model.append_extensions PerPage
+ ::DataMapper::Model.append_extensions Pagination
+ ::DataMapper::Collection.send(:include, Pagination)
+ ::DataMapper::Collection.send(:include, CollectionMethods)
+ end
+end
View
55 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/deprecation.rb
@@ -0,0 +1,55 @@
+module WillPaginate::Deprecation
+ class << self
+ def warn(message, stack = caller)
+ offending_line = origin_of_call(stack)
+ full_message = "DEPRECATION WARNING: #{message} (called from #{offending_line})"
+ logger = rails_logger || Kernel
+ logger.warn full_message
+ end
+
+ private
+
+ def rails_logger
+ defined?(Rails) && Rails.logger
+ end
+
+ def origin_of_call(stack)
+ lib_root = File.expand_path('../../..', __FILE__)
+ stack.find { |line| line.index(lib_root) != 0 } || stack.first
+ end
+ end
+
+ class Hash < ::Hash
+ def initialize(values = {})
+ super()
+ update values
+ @deprecated = {}
+ end
+
+ def []=(key, value)
+ check_deprecated(key, value)
+ super
+ end
+
+ def deprecate_key(*keys)
+ message = block_given? ? Proc.new : keys.pop
+ Array(keys).each { |key| @deprecated[key] = message }
+ end
+
+ def merge(another)
+ to_hash.update(another)
+ end
+
+ def to_hash
+ ::Hash.new.update(self)
+ end
+
+ private
+
+ def check_deprecated(key, value)
+ if msg = @deprecated[key] and (!msg.respond_to?(:call) or (msg = msg.call(key, value)))
+ WillPaginate::Deprecation.warn(msg)
+ end
+ end
+ end
+end
View
22 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/i18n.rb
@@ -0,0 +1,22 @@
+module WillPaginate
+ module I18n
+ def self.locale_dir
+ File.expand_path('../locale', __FILE__)
+ end
+
+ def self.load_path
+ Dir["#{locale_dir}/*.{rb,yml}"]
+ end
+
+ def will_paginate_translate(keys, options = {})
+ if defined? ::I18n
+ defaults = Array(keys).dup
+ defaults << Proc.new if block_given?
+ ::I18n.translate(defaults.shift, options.merge(:default => defaults, :scope => :will_paginate))
+ else
+ key = Array === keys ? keys.first : keys
+ yield key, options
+ end
+ end
+ end
+end
View
33 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/locale/en.yml
@@ -0,0 +1,33 @@
+en:
+ will_paginate:
+ previous_label: "&#8592; Previous"
+ next_label: "Next &#8594;"
+ page_gap: "&hellip;"
+
+ page_entries_info:
+ single_page:
+ zero: "No %{model} found"
+ one: "Displaying 1 %{model}"
+ other: "Displaying all %{count} %{model}"
+ single_page_html:
+ zero: "No %{model} found"
+ one: "Displaying <b>1</b> %{model}"
+ other: "Displaying <b>all&nbsp;%{count}</b> %{model}"
+
+ multi_page: "Displaying %{model} %{from} - %{to} of %{count} in total"
+ multi_page_html: "Displaying %{model} <b>%{from}&nbsp;-&nbsp;%{to}</b> of <b>%{count}</b> in total"
+
+ # models:
+ # entry:
+ # zero: entries
+ # one: entry
+ # few: entries
+ # other: entries
+
+ # line_item:
+ # page_entries_info:
+ # single_page:
+ # zero: "Your shopping cart is empty"
+ # one: "Displaying one item in your cart"
+ # other: "Displaying all %{count} items"
+ # multi_page: "Displaying items %{from} - %{to} of %{count} in total"
View
57 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/page_number.rb
@@ -0,0 +1,57 @@
+require 'delegate'
+require 'forwardable'
+
+module WillPaginate
+ # a module that page number exceptions are tagged with
+ module InvalidPage; end
+
+ # integer representing a page number
+ class PageNumber < DelegateClass(Integer)
+ # a value larger than this is not supported in SQL queries
+ BIGINT = 9223372036854775807
+
+ extend Forwardable
+
+ def initialize(value, name)
+ value = Integer(value)
+ if 'offset' == name ? (value < 0 or value > BIGINT) : value < 1
+ raise RangeError, "invalid #{name}: #{value.inspect}"
+ end
+ @name = name
+ super(value)
+ rescue ArgumentError, TypeError, RangeError => error
+ error.extend InvalidPage
+ raise error
+ end
+
+ alias_method :to_i, :__getobj__
+
+ def inspect
+ "#{@name} #{to_i}"
+ end
+
+ def to_offset(per_page)
+ PageNumber.new((to_i - 1) * per_page.to_i, 'offset')
+ end
+
+ def kind_of?(klass)
+ super || to_i.kind_of?(klass)
+ end
+ alias is_a? kind_of?
+ end
+
+ # Ultrahax: makes `Fixnum === current_page` checks pass
+ Numeric.extend Module.new {
+ def ===(obj)
+ obj.instance_of? PageNumber or super
+ end
+ }
+
+ # An idemptotent coercion method
+ def self.PageNumber(value, name = 'page')
+ case value
+ when PageNumber then value
+ else PageNumber.new(value, name)
+ end
+ end
+end
View
27 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/per_page.rb
@@ -0,0 +1,27 @@
+module WillPaginate
+ module PerPage
+ def per_page
+ defined?(@per_page) ? @per_page : WillPaginate.per_page
+ end
+
+ def per_page=(limit)
+ @per_page = limit.to_i
+ end
+
+ def self.extended(base)
+ base.extend Inheritance if base.is_a? Class
+ end
+
+ module Inheritance
+ def inherited(subclass)
+ super
+ subclass.per_page = self.per_page
+ end
+ end
+ end
+
+ extend PerPage
+
+ # default number of items per page
+ self.per_page = 30
+end
View
68 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/railtie.rb
@@ -0,0 +1,68 @@
+require 'will_paginate'
+require 'will_paginate/page_number'
+require 'will_paginate/collection'
+require 'will_paginate/i18n'
+
+module WillPaginate
+ class Railtie < Rails::Railtie
+ initializer "will_paginate" do |app|
+ ActiveSupport.on_load :active_record do
+ require 'will_paginate/active_record'
+ end
+
+ ActiveSupport.on_load :action_controller do
+ WillPaginate::Railtie.setup_actioncontroller
+ end
+
+ ActiveSupport.on_load :action_view do
+ require 'will_paginate/view_helpers/action_view'
+ end
+
+ self.class.add_locale_path config
+
+ # early access to ViewHelpers.pagination_options
+ require 'will_paginate/view_helpers'
+ end
+
+ def self.setup_actioncontroller
+ ( defined?(ActionDispatch::ExceptionWrapper) ?
+ ActionDispatch::ExceptionWrapper : ActionDispatch::ShowExceptions
+ ).send :include, ShowExceptionsPatch
+ ActionController::Base.extend ControllerRescuePatch
+ end
+
+ def self.add_locale_path(config)
+ config.i18n.railties_load_path.unshift(*WillPaginate::I18n.load_path)
+ end
+
+ # Extending the exception handler middleware so it properly detects
+ # WillPaginate::InvalidPage regardless of it being a tag module.
+ module ShowExceptionsPatch
+ extend ActiveSupport::Concern
+ included { alias_method_chain :status_code, :paginate }
+ def status_code_with_paginate(exception = @exception)
+ if exception.is_a?(WillPaginate::InvalidPage) or
+ (exception.respond_to?(:original_exception) &&
+ exception.original_exception.is_a?(WillPaginate::InvalidPage))
+ Rack::Utils.status_code(:not_found)
+ else
+ original_method = method(:status_code_without_paginate)
+ if original_method.arity != 0
+ original_method.call(exception)
+ else
+ original_method.call()
+ end
+ end
+ end
+ end
+
+ module ControllerRescuePatch
+ def rescue_from(*args, &block)
+ if idx = args.index(WillPaginate::InvalidPage)
+ args[idx] = args[idx].name
+ end
+ super(*args, &block)
+ end
+ end
+ end
+end
View
39 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/sequel.rb
@@ -0,0 +1,39 @@
+require 'sequel'
+require 'sequel/extensions/pagination'
+require 'will_paginate/collection'
+
+module WillPaginate
+ # Sequel already supports pagination; we only need to make the
+ # resulting dataset look a bit more like WillPaginate::Collection
+ module SequelMethods
+ include WillPaginate::CollectionMethods
+
+ def total_pages
+ page_count
+ end
+
+ def per_page
+ page_size
+ end
+
+ def size
+ current_page_record_count
+ end
+ alias length size
+
+ def total_entries
+ pagination_record_count
+ end
+
+ def out_of_bounds?
+ current_page > total_pages
+ end
+
+ # Current offset of the paginated collection
+ def offset
+ (current_page - 1) * per_page
+ end
+ end
+
+ Sequel::Dataset::Pagination.send(:include, SequelMethods)
+end
View
9 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/version.rb
@@ -0,0 +1,9 @@
+module WillPaginate #:nodoc:
+ module VERSION #:nodoc:
+ MAJOR = 3
+ MINOR = 0
+ TINY = 4
+
+ STRING = [MAJOR, MINOR, TINY].join('.')
+ end
+end
View
160 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/view_helpers.rb
@@ -0,0 +1,160 @@
+# encoding: utf-8
+require 'will_paginate/core_ext'
+require 'will_paginate/i18n'
+require 'will_paginate/deprecation'
+
+module WillPaginate
+ # = Will Paginate view helpers
+ #
+ # The main view helper is +will_paginate+. It renders the pagination links
+ # for the given collection. The helper itself is lightweight and serves only
+ # as a wrapper around LinkRenderer instantiation; the renderer then does
+ # all the hard work of generating the HTML.
+ module ViewHelpers
+ class << self
+ # Write to this hash to override default options on the global level:
+ #
+ # WillPaginate::ViewHelpers.pagination_options[:page_links] = false
+ #
+ attr_accessor :pagination_options
+ end
+
+ # default view options
+ self.pagination_options = Deprecation::Hash.new \
+ :class => 'pagination',
+ :previous_label => nil,
+ :next_label => nil,
+ :inner_window => 4, # links around the current page
+ :outer_window => 1, # links around beginning and end
+ :link_separator => ' ', # single space is friendly to spiders and non-graphic browsers
+ :param_name => :page,
+ :params => nil,
+ :page_links => true,
+ :container => true
+
+ label_deprecation = Proc.new { |key, value|
+ "set the 'will_paginate.#{key}' key in your i18n locale instead of editing pagination_options" if defined? Rails
+ }
+ pagination_options.deprecate_key(:previous_label, :next_label, &label_deprecation)
+ pagination_options.deprecate_key(:renderer) { |key, _| "pagination_options[#{key.inspect}] shouldn't be set globally" }
+
+ include WillPaginate::I18n
+
+ # Returns HTML representing page links for a WillPaginate::Collection-like object.
+ # In case there is no more than one page in total, nil is returned.
+ #
+ # ==== Options
+ # * <tt>:class</tt> -- CSS class name for the generated DIV (default: "pagination")
+ # * <tt>:previous_label</tt> -- default: "« Previous"
+ # * <tt>:next_label</tt> -- default: "Next »"
+ # * <tt>:inner_window</tt> -- how many links are shown around the current page (default: 4)
+ # * <tt>:outer_window</tt> -- how many links are around the first and the last page (default: 1)
+ # * <tt>:link_separator</tt> -- string separator for page HTML elements (default: single space)
+ # * <tt>:param_name</tt> -- parameter name for page number in URLs (default: <tt>:page</tt>)
+ # * <tt>:params</tt> -- additional parameters when generating pagination links
+ # (eg. <tt>:controller => "foo", :action => nil</tt>)
+ # * <tt>:renderer</tt> -- class name, class or instance of a link renderer (default in Rails:
+ # <tt>WillPaginate::ActionView::LinkRenderer</tt>)
+ # * <tt>:page_links</tt> -- when false, only previous/next links are rendered (default: true)
+ # * <tt>:container</tt> -- toggles rendering of the DIV container for pagination links, set to
+ # false only when you are rendering your own pagination markup (default: true)
+ #
+ # All options not recognized by will_paginate will become HTML attributes on the container
+ # element for pagination links (the DIV). For example:
+ #
+ # <%= will_paginate @posts, :style => 'color:blue' %>
+ #
+ # will result in:
+ #
+ # <div class="pagination" style="color:blue"> ... </div>
+ #
+ def will_paginate(collection, options = {})
+ # early exit if there is nothing to render
+ return nil unless collection.total_pages > 1
+
+ options = WillPaginate::ViewHelpers.pagination_options.merge(options)
+
+ options[:previous_label] ||= will_paginate_translate(:previous_label) { '&#8592; Previous' }
+ options[:next_label] ||= will_paginate_translate(:next_label) { 'Next &#8594;' }
+
+ # get the renderer instance
+ renderer = case options[:renderer]
+ when nil
+ raise ArgumentError, ":renderer not specified"
+ when String
+ klass = if options[:renderer].respond_to? :constantize then options[:renderer].constantize
+ else Object.const_get(options[:renderer]) # poor man's constantize
+ end
+ klass.new
+ when Class then options[:renderer].new
+ else options[:renderer]
+ end
+ # render HTML for pagination
+ renderer.prepare collection, options, self
+ renderer.to_html
+ end
+
+ # Renders a message containing number of displayed vs. total entries.
+ #
+ # <%= page_entries_info @posts %>
+ # #-> Displaying posts 6 - 12 of 26 in total
+ #
+ # The default output contains HTML. Use ":html => false" for plain text.
+ def page_entries_info(collection, options = {})
+ model = options[:model]
+ model = collection.first.class unless model or collection.empty?
+ model ||= 'entry'
+ model_key = if model.respond_to? :model_name
+ model.model_name.i18n_key # ActiveModel::Naming
+ else
+ model.to_s.underscore
+ end
+
+ if options.fetch(:html, true)
+ b, eb = '<b>', '</b>'
+ sp = '&nbsp;'
+ html_key = '_html'
+ else
+ b = eb = html_key = ''
+ sp = ' '
+ end
+
+ model_count = collection.total_pages > 1 ? 5 : collection.size
+ defaults = ["models.#{model_key}"]
+ defaults << Proc.new { |_, opts|
+ if model.respond_to? :model_name
+ model.model_name.human(:count => opts[:count])
+ else
+ name = model_key.to_s.tr('_', ' ')
+ raise "can't pluralize model name: #{model.inspect}" unless name.respond_to? :pluralize
+ opts[:count] == 1 ? name : name.pluralize
+ end
+ }
+ model_name = will_paginate_translate defaults, :count => model_count
+
+ if collection.total_pages < 2
+ i18n_key = :"page_entries_info.single_page#{html_key}"
+ keys = [:"#{model_key}.#{i18n_key}", i18n_key]
+
+ will_paginate_translate keys, :count => collection.total_entries, :model => model_name do |_, opts|
+ case opts[:count]
+ when 0; "No #{opts[:model]} found"
+ when 1; "Displaying #{b}1#{eb} #{opts[:model]}"
+ else "Displaying #{b}all#{sp}#{opts[:count]}#{eb} #{opts[:model]}"
+ end
+ end
+ else
+ i18n_key = :"page_entries_info.multi_page#{html_key}"
+ keys = [:"#{model_key}.#{i18n_key}", i18n_key]
+ params = {
+ :model => model_name, :count => collection.total_entries,
+ :from => collection.offset + 1, :to => collection.offset + collection.length
+ }
+ will_paginate_translate keys, params do |_, opts|
+ %{Displaying %s #{b}%d#{sp}-#{sp}%d#{eb} of #{b}%d#{eb} in total} %
+ [ opts[:model], opts[:from], opts[:to], opts[:count] ]
+ end
+ end
+ end
+ end
+end
View
148 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/view_helpers/action_view.rb
@@ -0,0 +1,148 @@
+require 'will_paginate/view_helpers'
+require 'will_paginate/view_helpers/link_renderer'
+
+module WillPaginate
+ # = ActionView helpers
+ #
+ # This module serves for availability in ActionView templates. It also adds a new
+ # view helper: +paginated_section+.
+ #
+ # == Using the helper without arguments
+ # If the helper is called without passing in the collection object, it will
+ # try to read from the instance variable inferred by the controller name.
+ # For example, calling +will_paginate+ while the current controller is
+ # PostsController will result in trying to read from the <tt>@posts</tt>
+ # variable. Example:
+ #
+ # <%= will_paginate :id => true %>
+ #
+ # ... will result in <tt>@post</tt> collection getting paginated:
+ #
+ # <div class="pagination" id="posts_pagination"> ... </div>
+ #
+ module ActionView
+ include ViewHelpers
+
+ def will_paginate(collection = nil, options = {}) #:nodoc:
+ options, collection = collection, nil if collection.is_a? Hash
+ collection ||= infer_collection_from_controller
+
+ options = options.symbolize_keys
+ options[:renderer] ||= LinkRenderer
+
+ super(collection, options).try(:html_safe)
+ end
+
+ def page_entries_info(collection = nil, options = {}) #:nodoc:
+ options, collection = collection, nil if collection.is_a? Hash
+ collection ||= infer_collection_from_controller
+
+ super(collection, options.symbolize_keys)
+ end
+
+ # Wrapper for rendering pagination links at both top and bottom of a block
+ # of content.
+ #
+ # <% paginated_section @posts do %>
+ # <ol id="posts">
+ # <% for post in @posts %>
+ # <li> ... </li>
+ # <% end %>
+ # </ol>
+ # <% end %>
+ #
+ # will result in:
+ #
+ # <div class="pagination"> ... </div>
+ # <ol id="posts">
+ # ...
+ # </ol>
+ # <div class="pagination"> ... </div>
+ #
+ # Arguments are passed to a <tt>will_paginate</tt> call, so the same options
+ # apply. Don't use the <tt>:id</tt> option; otherwise you'll finish with two
+ # blocks of pagination links sharing the same ID (which is invalid HTML).
+ def paginated_section(*args, &block)
+ pagination = will_paginate(*args)
+ if pagination
+ pagination + capture(&block) + pagination
+ else
+ capture(&block)
+ end
+ end
+
+ def will_paginate_translate(keys, options = {})
+ if respond_to? :translate
+ if Array === keys
+ defaults = keys.dup
+ key = defaults.shift
+ else
+ defaults = nil
+ key = keys
+ end
+ translate(key, options.merge(:default => defaults, :scope => :will_paginate))
+ else
+ super
+ end
+ end
+
+ protected
+
+ def infer_collection_from_controller
+ collection_name = "@#{controller.controller_name}"
+ collection = instance_variable_get(collection_name)
+ raise ArgumentError, "The #{collection_name} variable appears to be empty. Did you " +
+ "forget to pass the collection object for will_paginate?" if collection.nil?
+ collection
+ end
+
+ class LinkRenderer < ViewHelpers::LinkRenderer
+ protected
+
+ def default_url_params
+ {}
+ end
+
+ def url(page)
+ @base_url_params ||= begin
+ url_params = merge_get_params(default_url_params)
+ merge_optional_params(url_params)
+ end
+
+ url_params = @base_url_params.dup
+ add_current_page_param(url_params, page)
+
+ @template.url_for(url_params)
+ end
+
+ def merge_get_params(url_params)
+ if @template.respond_to? :request and @template.request and @template.request.get?
+ symbolized_update(url_params, @template.params)
+ end
+ url_params
+ end
+
+ def merge_optional_params(url_params)
+ symbolized_update(url_params, @options[:params]) if @options[:params]
+ url_params
+ end
+
+ def add_current_page_param(url_params, page)
+ unless param_name.index(/[^\w-]/)
+ url_params[param_name.to_sym] = page
+ else
+ page_param = parse_query_parameters("#{param_name}=#{page}")
+ symbolized_update(url_params, page_param)
+ end
+ end
+
+ private
+
+ def parse_query_parameters(params)
+ Rack::Utils.parse_nested_query(params)
+ end
+ end
+
+ ::ActionView::Base.send :include, self
+ end
+end
View
131 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/view_helpers/link_renderer.rb
@@ -0,0 +1,131 @@
+require 'cgi'
+require 'will_paginate/core_ext'
+require 'will_paginate/view_helpers'
+require 'will_paginate/view_helpers/link_renderer_base'
+
+module WillPaginate
+ module ViewHelpers
+ # This class does the heavy lifting of actually building the pagination
+ # links. It is used by +will_paginate+ helper internally.
+ class LinkRenderer < LinkRendererBase
+
+ # * +collection+ is a WillPaginate::Collection instance or any other object
+ # that conforms to that API
+ # * +options+ are forwarded from +will_paginate+ view helper
+ # * +template+ is the reference to the template being rendered
+ def prepare(collection, options, template)
+ super(collection, options)
+ @template = template
+ @container_attributes = @base_url_params = nil
+ end
+
+ # Process it! This method returns the complete HTML string which contains
+ # pagination links. Feel free to subclass LinkRenderer and change this
+ # method as you see fit.
+ def to_html
+ html = pagination.map do |item|
+ item.is_a?(Fixnum) ?
+ page_number(item) :
+ send(item)
+ end.join(@options[:link_separator])
+
+ @options[:container] ? html_container(html) : html
+ end
+
+ # Returns the subset of +options+ this instance was initialized with that
+ # represent HTML attributes for the container element of pagination links.
+ def container_attributes
+ @container_attributes ||= @options.except(*(ViewHelpers.pagination_options.keys + [:renderer] - [:class]))
+ end
+
+ protected
+
+ def page_number(page)
+ unless page == current_page
+ link(page, page, :rel => rel_value(page))
+ else
+ tag(:em, page, :class => 'current')
+ end
+ end
+
+ def gap
+ text = @template.will_paginate_translate(:page_gap) { '&hellip;' }
+ %(<span class="gap">#{text}</span>)
+ end
+
+ def previous_page
+ num = @collection.current_page > 1 && @collection.current_page - 1
+ previous_or_next_page(num, @options[:previous_label], 'previous_page')
+ end
+
+ def next_page
+ num = @collection.current_page < total_pages && @collection.current_page + 1
+ previous_or_next_page(num, @options[:next_label], 'next_page')
+ end
+
+ def previous_or_next_page(page, text, classname)
+ if page
+ link(text, page, :class => classname)
+ else
+ tag(:span, text, :class => classname + ' disabled')
+ end
+ end
+
+ def html_container(html)
+ tag(:div, html, container_attributes)
+ end
+
+ # Returns URL params for +page_link_or_span+, taking the current GET params
+ # and <tt>:params</tt> option into account.
+ def url(page)
+ raise NotImplementedError
+ end
+
+ private
+
+ def param_name
+ @options[:param_name].to_s
+ end
+
+ def link(text, target, attributes = {})
+ if target.is_a? Fixnum
+ attributes[:rel] = rel_value(target)
+ target = url(target)
+ end
+ attributes[:href] = target
+ tag(:a, text, attributes)
+ end
+
+ def tag(name, value, attributes = {})
+ string_attributes = attributes.inject('') do |attrs, pair|
+ unless pair.last.nil?
+ attrs << %( #{pair.first}="#{CGI::escapeHTML(pair.last.to_s)}")
+ end
+ attrs
+ end
+ "<#{name}#{string_attributes}>#{value}</#{name}>"
+ end
+
+ def rel_value(page)
+ case page
+ when @collection.current_page - 1; 'prev' + (page == 1 ? ' start' : '')
+ when @collection.current_page + 1; 'next'
+ when 1; 'start'
+ end
+ end
+
+ def symbolized_update(target, other)
+ other.each do |key, value|
+ key = key.to_sym
+ existing = target[key]
+
+ if value.is_a?(Hash) and (existing.is_a?(Hash) or existing.nil?)
+ symbolized_update(existing || (target[key] = {}), value)
+ else
+ target[key] = value
+ end
+ end
+ end
+ end
+ end
+end
View
77 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/view_helpers/link_renderer_base.rb
@@ -0,0 +1,77 @@
+module WillPaginate
+ module ViewHelpers
+ # This class does the heavy lifting of actually building the pagination
+ # links. It is used by +will_paginate+ helper internally.
+ class LinkRendererBase
+
+ # * +collection+ is a WillPaginate::Collection instance or any other object
+ # that conforms to that API
+ # * +options+ are forwarded from +will_paginate+ view helper
+ def prepare(collection, options)
+ @collection = collection
+ @options = options
+
+ # reset values in case we're re-using this instance
+ @total_pages = nil
+ end
+
+ def pagination
+ items = @options[:page_links] ? windowed_page_numbers : []
+ items.unshift :previous_page
+ items.push :next_page
+ end
+
+ protected
+
+ # Calculates visible page numbers using the <tt>:inner_window</tt> and
+ # <tt>:outer_window</tt> options.
+ def windowed_page_numbers
+ inner_window, outer_window = @options[:inner_window].to_i, @options[:outer_window].to_i
+ window_from = current_page - inner_window
+ window_to = current_page + inner_window
+
+ # adjust lower or upper limit if other is out of bounds
+ if window_to > total_pages
+ window_from -= window_to - total_pages
+ window_to = total_pages
+ end
+ if window_from < 1
+ window_to += 1 - window_from
+ window_from = 1
+ window_to = total_pages if window_to > total_pages
+ end
+
+ # these are always visible
+ middle = window_from..window_to
+
+ # left window
+ if outer_window + 3 < middle.first # there's a gap
+ left = (1..(outer_window + 1)).to_a
+ left << :gap
+ else # runs into visible pages
+ left = 1...middle.first
+ end
+
+ # right window
+ if total_pages - outer_window - 2 > middle.last # again, gap
+ right = ((total_pages - outer_window)..total_pages).to_a
+ right.unshift :gap
+ else # runs into visible pages
+ right = (middle.last + 1)..total_pages
+ end
+
+ left.to_a + middle.to_a + right.to_a
+ end
+
+ private
+
+ def current_page
+ @collection.current_page
+ end
+
+ def total_pages
+ @total_pages ||= @collection.total_pages
+ end
+ end
+ end
+end
View
26 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/view_helpers/merb.rb
@@ -0,0 +1,26 @@
+require 'will_paginate/core_ext'
+require 'will_paginate/view_helpers'
+require 'will_paginate/view_helpers/link_renderer'
+
+module WillPaginate
+ module Merb
+ include ViewHelpers
+
+ def will_paginate(collection, options = {}) #:nodoc:
+ options = options.merge(:renderer => LinkRenderer) unless options[:renderer]
+ super(collection, options)
+ end
+
+ class LinkRenderer < ViewHelpers::LinkRenderer
+ protected
+
+ def url(page)
+ params = @template.request.params.except(:action, :controller).merge(param_name => page)
+ @template.url(:this, params)
+ end
+ end
+
+ ::Merb::AbstractController.send(:include, self)
+ end
+end
+
View
41 vendor/bundle/gems/will_paginate-3.0.4/lib/will_paginate/view_helpers/sinatra.rb
@@ -0,0 +1,41 @@
+require 'sinatra/base'
+require 'will_paginate/view_helpers'
+require 'will_paginate/view_helpers/link_renderer'
+
+module WillPaginate
+ module Sinatra
+ module Helpers
+ include ViewHelpers
+
+ def will_paginate(collection, options = {}) #:nodoc:
+ options = options.merge(:renderer => LinkRenderer) unless options[:renderer]
+ super(collection, options)
+ end
+ end
+
+ class LinkRenderer < ViewHelpers::LinkRenderer
+ protected
+
+ def url(page)
+ str = File.join(request.script_name.to_s, request.path_info)
+ params = request.GET.merge(param_name.to_s => page.to_s)
+ params.update @options[:params] if @options[:params]
+ str << '?' << build_query(params)
+ end
+
+ def request
+ @template.request
+ end
+
+ def build_query(params)
+ Rack::Utils.build_nested_query params
+ end
+ end
+
+ def self.registered(app)
+ app.helpers Helpers
+ end
+
+ ::Sinatra.register self
+ end
+end
View
29 vendor/bundle/gems/will_paginate-3.0.4/spec/ci.rb
@@ -0,0 +1,29 @@
+#!/usr/bin/env ruby
+databases = %w[ sqlite3 mysql mysql2 postgres ]
+databases.delete 'mysql2' if ENV['BUNDLE_GEMFILE'].to_s.include? 'rails3.0'
+
+def announce(name, msg)
+ puts "\n\e[1;33m[#{name}] #{msg}\e[m\n"
+end
+
+def system(*args)
+ puts "$ #{args.join(' ')}"
+ super
+end
+
+if ENV['TRAVIS']
+ system "mysql -e 'create database will_paginate;' >/dev/null"
+ abort "failed to create mysql database" unless $?.success?
+ system "psql -c 'create database will_paginate;' -U postgres >/dev/null"
+ abort "failed to create postgres database" unless $?.success?
+end
+
+failed = false
+
+for db in databases
+ announce "DB", db
+ ENV['DB'] = db
+ failed = true unless system %(rake)
+end
+
+exit 1 if failed
View
139 vendor/bundle/gems/will_paginate-3.0.4/spec/collection_spec.rb
@@ -0,0 +1,139 @@
+require 'will_paginate/array'
+require 'spec_helper'
+
+describe WillPaginate::Collection do
+
+ before :all do
+ @simple = ('a'..'e').to_a
+ end
+
+ it "should be a subset of original collection" do
+ @simple.paginate(:page => 1, :per_page => 3).should == %w( a b c )
+ end
+
+ it "can be shorter than per_page if on last page" do
+ @simple.paginate(:page => 2, :per_page => 3).should == %w( d e )
+ end
+
+ it "should include whole collection if per_page permits" do
+ @simple.paginate(:page => 1, :per_page => 5).should == @simple
+ end
+
+ it "should be empty if out of bounds" do
+ @simple.paginate(:page => 2, :per_page => 5).should be_empty
+ end
+
+ it "should default to 1 as current page and 30 per-page" do
+ result = (1..50).to_a.paginate
+ result.current_page.should == 1
+ result.size.should == 30
+ end
+
+ it "should give total_entries precedence over actual size" do
+ %w(a b c).paginate(:total_entries => 5).total_entries.should == 5
+ end
+
+ it "should be an augmented Array" do
+ entries = %w(a b c)
+ collection = create(2, 3, 10) do |pager|
+ pager.replace(entries).should == entries
+ end
+
+ collection.should == entries
+ for method in %w(total_pages each offset size current_page per_page total_entries)
+ collection.should respond_to(method)
+ end
+ collection.should be_kind_of(Array)
+ collection.entries.should be_instance_of(Array)
+ # TODO: move to another expectation:
+ collection.offset.should == 3
+ collection.total_pages.should == 4
+ collection.should_not be_out_of_bounds
+ end
+
+ describe "previous/next pages" do
+ it "should have previous_page nil when on first page" do
+ collection = create(1, 1, 3)
+ collection.previous_page.should be_nil
+ collection.next_page.should == 2
+ end
+
+ it "should have both prev/next pages" do
+ collection = create(2, 1, 3)
+ collection.previous_page.should == 1
+ collection.next_page.should == 3
+ end
+
+ it "should have next_page nil when on last page" do
+ collection = create(3, 1, 3)
+ collection.previous_page.should == 2
+ collection.next_page.should be_nil
+ end
+ end
+
+ describe "out of bounds" do
+ it "is out of bounds when page number is too high" do
+ create(2, 3, 2).should be_out_of_bounds
+ end
+
+ it "isn't out of bounds when inside collection" do
+ create(1, 3, 2).should_not be_out_of_bounds
+ end
+
+ it "isn't out of bounds when the collection is empty" do
+ collection = create(1, 3, 0)
+ collection.should_not be_out_of_bounds
+ collection.total_pages.should == 1
+ end
+ end
+
+ describe "guessing total count" do
+ it "can guess when collection is shorter than limit" do
+ collection = create { |p| p.replace array }
+ collection.total_entries.should == 8
+ end
+
+ it "should allow explicit total count to override guessed" do
+ collection = create(2, 5, 10) { |p| p.replace array }
+ collection.total_entries.should == 10
+ end
+
+ it "should not be able to guess when collection is same as limit" do
+ collection = create { |p| p.replace array(5) }
+ collection.total_entries.should be_nil
+ end
+
+ it "should not be able to guess when collection is empty" do
+ collection = create { |p| p.replace array(0) }
+ collection.total_entries.should be_nil
+ end
+
+ it "should be able to guess when collection is empty and this is the first page" do
+ collection = create(1) { |p| p.replace array(0) }
+ collection.total_entries.should == 0
+ end
+ end
+
+ it "should not respond to page_count anymore" do
+ Proc.new { create.page_count }.should raise_error(NoMethodError)
+ end
+
+ it "inherits per_page from global value" do
+ collection = described_class.new(1)
+ collection.per_page.should == 30
+ end
+
+ private
+
+ def create(page = 2, limit = 5, total = nil, &block)
+ if block_given?
+ described_class.create(page, limit, total, &block)
+ else
+ described_class.new(page, limit, total)
+ end
+ end
+
+ def array(size = 3)
+ Array.new(size)
+ end
+end
View
12 vendor/bundle/gems/will_paginate-3.0.4/spec/console
@@ -0,0 +1,12 @@
+#!/usr/bin/env ruby
+irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
+opts = %w[ --simple-prompt -rirb/completion ]
+if ARGV.include? '-dm'
+ opts << '-rwill_paginate/data_mapper' << '-rfinders/data_mapper_test_connector'
+elsif ARGV.include? '-seq'
+ opts << '-rwill_paginate/sequel' << '-rfinders/sequel_test_connector'
+else
+ opts << '-rconsole_fixtures'
+end
+
+exec 'bundle', 'exec', irb, '-Ilib:spec', *opts
View
28 vendor/bundle/gems/will_paginate-3.0.4/spec/console_fixtures.rb
@@ -0,0 +1,28 @@
+require 'bundler'
+Bundler.setup
+
+require 'will_paginate/active_record'
+require 'finders/activerecord_test_connector'
+
+ActiverecordTestConnector.setup
+
+windows = RUBY_PLATFORM =~ /(:?mswin|mingw)/
+# used just for the `color` method
+log_subscriber = ActiveSupport::LogSubscriber.log_subscribers.first
+
+IGNORE_SQL = /\b(sqlite_master|sqlite_version)\b|^(CREATE TABLE|PRAGMA)\b/
+
+ActiveSupport::Notifications.subscribe(/^sql\./) do |*args|
+ data = args.last
+ unless data[:name] =~ /^Fixture/ or data[:sql] =~ IGNORE_SQL
+ if windows
+ puts data[:sql]
+ else
+ puts log_subscriber.send(:color, data[:sql], :cyan)
+ end
+ end
+end
+
+# load all fixtures
+ActiverecordTestConnector::Fixtures.create_fixtures \
+ ActiverecordTestConnector::FIXTURES_PATH, ActiveRecord::Base.connection.tables
View
22 vendor/bundle/gems/will_paginate-3.0.4/spec/database.yml
@@ -0,0 +1,22 @@
+sqlite3:
+ database: ":memory:"
+ adapter: sqlite3
+ timeout: 500
+
+mysql:
+ adapter: mysql
+ database: will_paginate
+ username:
+ encoding: utf8
+
+mysql2:
+ adapter: mysql2
+ database: will_paginate
+ username:
+ encoding: utf8
+
+postgres:
+ adapter: postgresql
+ database: will_paginate
+ username: postgres
+ min_messages: warning
View
556 vendor/bundle/gems/will_paginate-3.0.4/spec/finders/active_record_spec.rb
@@ -0,0 +1,556 @@
+require 'spec_helper'
+require 'will_paginate/active_record'
+require File.expand_path('../activerecord_test_connector', __FILE__)
+
+ActiverecordTestConnector.setup
+abort unless ActiverecordTestConnector.able_to_connect
+
+describe WillPaginate::ActiveRecord do
+
+ extend ActiverecordTestConnector::FixtureSetup
+
+ fixtures :topics, :replies, :users, :projects, :developers_projects
+
+ it "should integrate with ActiveRecord::Base" do
+ ActiveRecord::Base.should respond_to(:paginate)
+ end
+
+ it "should paginate" do
+ lambda {
+ users = User.paginate(:page => 1, :per_page => 5).to_a
+ users.length.should == 5
+ }.should run_queries(2)
+ end
+
+ it "should fail when encountering unknown params" do
+ lambda {
+ User.paginate :foo => 'bar', :page => 1, :per_page => 4
+ }.should raise_error(ArgumentError)
+ end
+
+ describe "relation" do
+ it "should return a relation" do
+ rel = nil
+ lambda {
+ rel = Developer.paginate(:page => 1)
+ rel.per_page.should == 10
+ rel.current_page.should == 1
+ }.should run_queries(0)
+
+ lambda {
+ rel.total_pages.should == 2
+ }.should run_queries(1)
+ end
+
+ it "should keep per-class per_page number" do
+ rel = Developer.order('id').paginate(:page => 1)
+ rel.per_page.should == 10
+ end
+
+ it "should be able to change per_page number" do
+ rel = Developer.order('id').paginate(:page => 1).limit(5)
+ rel.per_page.should == 5
+ end
+
+ it "remembers pagination in sub-relations" do
+ rel = Topic.paginate(:page => 2, :per_page => 3)
+ lambda {
+ rel.total_entries.should == 4
+ }.should run_queries(1)
+ rel = rel.mentions_activerecord
+ rel.current_page.should == 2
+ rel.per_page.should == 3
+ lambda {
+ rel.total_entries.should == 1
+ }.should run_queries(1)
+ end
+
+ it "supports the page() method" do
+ rel = Developer.page('1').order('id')
+ rel.current_page.should == 1
+ rel.per_page.should == 10
+ rel.offset.should == 0
+
+ rel = rel.limit(5).page(2)
+ rel.per_page.should == 5
+ rel.offset.should == 5
+ end
+
+ it "raises on invalid page number" do
+ lambda {
+ Developer.page('foo')
+ }.should raise_error(ArgumentError)
+ end
+
+ it "supports first limit() then page()" do
+ rel = Developer.limit(3).page(3)
+ rel.offset.should == 6
+ end
+
+ it "supports first page() then limit()" do
+ rel = Developer.page(3).limit(3)
+ rel.offset.should == 6
+ end
+
+ it "supports #first" do
+ rel = Developer.order('id').page(2).per_page(4)
+ rel.first.should == users(:dev_5)
+ rel.first(2).should == users(:dev_5, :dev_6)
+ end
+
+ it "supports #last" do
+ rel = Developer.order('id').page(2).per_page(4)
+ rel.last.should == users(:dev_8)
+ rel.last(2).should == users(:dev_7, :dev_8)
+ rel.page(3).last.should == users(:poor_jamis)
+ end
+
+ it "keeps pagination data after 'scoped'" do
+ rel = Developer.page(2).scoped
+ rel.per_page.should == 10
+ rel.offset.should == 10
+ rel.current_page.should == 2
+ end
+ end
+
+ describe "counting" do
+ it "should guess the total count" do
+ lambda {
+ topics = Topic.paginate :page => 2, :per_page => 3
+ topics.total_entries.should == 4
+ }.should run_queries(1)
+ end
+
+ it "should guess that there are no records" do
+ lambda {
+ topics = Topic.where(:project_id => 999).paginate :page => 1, :per_page => 3
+ topics.total_entries.should == 0
+ }.should run_queries(1)
+ end
+
+ it "forgets count in sub-relations" do
+ lambda {
+ topics = Topic.paginate :page => 1, :per_page => 3
+ topics.total_entries.should == 4
+ topics.where('1 = 1').total_entries.should == 4
+ }.should run_queries(2)
+ end
+
+ it "remembers custom count options in sub-relations" do
+ topics = Topic.paginate :page => 1, :per_page => 3, :count => {:conditions => "title LIKE '%futurama%'"}
+ topics.total_entries.should == 1
+ topics.length.should == 3
+ lambda {
+ topics.order('id').total_entries.should == 1
+ }.should run_queries(1)
+ end
+
+ it "supports empty? method" do
+ topics = Topic.paginate :page => 1, :per_page => 3
+ lambda {
+ topics.should_not be_empty
+ }.should run_queries(1)
+ end
+
+ it "support empty? for grouped queries" do
+ topics = Topic.group(:project_id).paginate :page => 1, :per_page => 3
+ lambda {
+ topics.should_not be_empty
+ }.should run_queries(1)
+ end
+
+ it "supports `size` for grouped queries" do
+ topics = Topic.group(:project_id).paginate :page => 1, :per_page => 3
+ lambda {
+ topics.size.should == {nil=>2, 1=>2}
+ }.should run_queries(1)
+ end
+
+ it "overrides total_entries count with a fixed value" do
+ lambda {
+ topics = Topic.paginate :page => 1, :per_page => 3, :total_entries => 999
+ topics.total_entries.should == 999
+ # value is kept even in sub-relations
+ topics.where('1 = 1').total_entries.should == 999
+ }.should run_queries(0)
+ end
+
+ it "supports a non-int for total_entries" do
+ topics = Topic.paginate :page => 1, :per_page => 3, :total_entries => "999"
+ topics.total_entries.should == 999
+ end
+
+ it "removes :include for count" do
+ lambda {
+ developers = Developer.paginate(:page => 1, :per_page => 1).includes(:projects)
+ developers.total_entries.should == 11
+ $query_sql.last.should_not =~ /\bJOIN\b/
+ }.should run_queries(1)
+ end
+
+ it "keeps :include for count when they are referenced in :conditions" do
+ developers = Developer.paginate(:page => 1, :per_page => 1).includes(:projects)
+ with_condition = developers.where('projects.id > 1')
+ with_condition.total_entries.should == 1
+
+ $query_sql.last.should =~ /\bJOIN\b/
+ end
+
+ it "should count with group" do
+ Developer.group(:salary).page(1).total_entries.should == 4
+ end
+
+ it "should not have zero total_pages when the result set is empty" do
+ Developer.where("1 = 2").page(1).total_pages.should == 1
+ end
+ end
+
+ it "should not ignore :select parameter when it says DISTINCT" do
+ users = User.select('DISTINCT salary').paginate :page => 2
+ users.total_entries.should == 5
+ end
+
+ describe "paginate_by_sql" do
+ it "should respond" do
+ User.should respond_to(:paginate_by_sql)
+ end
+
+ it "should paginate" do
+ lambda {
+ sql = "select content from topics where content like '%futurama%'"
+ topics = Topic.paginate_by_sql sql, :page => 1, :per_page => 1
+ topics.total_entries.should == 1
+ topics.first.attributes.has_key?('title').should be_false
+ }.should run_queries(2)
+ end
+
+ it "should respect total_entries setting" do
+ lambda {
+ sql = "select content from topics"
+ topics = Topic.paginate_by_sql sql, :page => 1, :per_page => 1, :total_entries => 999
+ topics.total_entries.should == 999
+ }.should run_queries(1)
+ end
+
+ it "defaults to page 1" do
+ sql = "select content from topics"
+ topics = Topic.paginate_by_sql sql, :page => nil, :per_page => 1
+ topics.current_page.should == 1
+ topics.size.should == 1
+ end
+
+ it "should strip the order when counting" do
+ lambda {
+ sql = "select id, title, content from topics order by topics.title"
+ topics = Topic.paginate_by_sql sql, :page => 1, :per_page => 2
+ topics.first.should == topics(:ar)
+ }.should run_queries(2)
+
+ $query_sql.last.should include('COUNT')
+ $query_sql.last.should_not include('order by topics.title')
+ end
+
+ it "shouldn't change the original query string" do
+ query = 'select * from topics where 1 = 2'
+ original_query = query.dup
+ Topic.paginate_by_sql(query, :page => 1)
+ query.should == original_query
+ end
+ end
+
+ it "doesn't mangle options" do
+ options = { :page => 1 }
+ options.expects(:delete).never
+ options_before = options.dup
+
+ Topic.paginate(options)
+ options.should == options_before
+ end
+
+ it "should get first page of Topics with a single query" do
+ lambda {
+ result = Topic.paginate :page => nil
+ result.to_a # trigger loading of records
+ result.current_page.should == 1
+ result.total_pages.should == 1
+ result.size.should == 4
+ }.should run_queries(1)
+ end
+
+ it "should get second (inexistent) page of Topics, requiring 2 queries" do
+ lambda {
+ result = Topic.paginate :page => 2
+ result.total_pages.should == 1
+ result.should be_empty
+ }.should run_queries(2)
+ end
+
+ it "should paginate with :order" do
+ result = Topic.paginate :page => 1, :order => 'created_at DESC'
+ result.should == topics(:futurama, :harvey_birdman, :rails, :ar).reverse
+ result.total_pages.should == 1
+ end
+
+ it "should paginate with :conditions" do
+ result = Topic.paginate :page => 1, :order => 'id ASC',
+ :conditions => ["created_at > ?", 30.minutes.ago]
+ result.should == topics(:rails, :ar)
+ result.total_pages.should == 1
+ end
+
+ it "should paginate with :include and :conditions" do
+ result = Topic.paginate \
+ :page => 1,
+ :include => :replies,
+ :conditions => "replies.content LIKE 'Bird%' ",