module Paginate
module Helper
# Display pagination based on the collection and current page.
#
# <%= paginate @posts %>
# <%= paginate @posts, options %>
# <%= paginate @posts, posts_path, options %>
#
# The available options are:
#
# * :url: the URL which page numbers will be appended to. Can be proc or string.
# * :id: the HTML id that will identify the pagination block.
# * :size: the page size. When not specified will default to Paginate::Config.size.
# * :param_name: the page param name. When not specified will default to Paginate::Config.param_name.
#
# <%= paginate @posts, proc {|page| posts_path(page) }
# <%= paginate @posts, :url => proc {|page| posts_path(page) }
#
# You don't have to specify the URL; the current requested URI will be used if you don't provide it.
#
def paginate(collection, *args)
options = args.extract_options!
param_name = [options[:param_name], Paginate::Config.param_name, :page].compact.first
options.merge!({
:collection => collection,
:page => params[param_name],
:param_name => param_name,
:fullpath => request.respond_to?(:fullpath) ? request.fullpath : request.request_uri
})
options.merge!(:url => args.first) if args.any?
Paginate::Renderer.new(options).render
end
# Override the original render method, so we can strip the additional
# item from the collection, without changing your workflow with the
# iterate "always felt dirty" method.
#
# To render a paginated set, just pass the :paginate => true option.
# You can also provide a custom size with :size => number
#
# <%= render @posts, :paginate => true %>
# <%= render @pots, :paginate => true, :size => 20 %>
# <%= render "post", :collection => @posts, :paginate => true, :size => 20 %>
#
def render(*args, &block)
options = args.extract_options!
paginated = options.delete(:paginate)
size = options.delete(:size) { Paginate::Config.size }
return super(*[*args, options], &block) unless paginated
collection = options.delete(:collection) { args.shift }
collection = collection[0, size]
super(collection, *[*args, options], &block)
end
# In order to iterate the correct items you have to skip the last collection's item.
# We added this helper to automatically skip the last item only if there's a next page.
#
# <% iterate @items do |item| %>
# <% end %>
#
# If you want to grab the iteration index as well just expect it as a block parameter.
#
# <% iterate @items do |item, i|
# <% end %>
#
# If you set a custom size while fetching items from database, you need to inform it while iterating.
#
# @items = Item.paginate(:page => 1, :size => 5)
#
# Then in your view:
#
# <% iterate @items, :size => 5 do |item| %>
# <% end %>
#
# You can receive the iteration counter by expecting two arguments.
#
# <% iterate @items do |item, i| do %>
# <% end %>
#
def iterate(collection, options = {}, &block)
options.reverse_merge!(:size => Paginate::Config.size)
yield_index = block.arity == 2
collection[0, options[:size]].each_with_index do |item, i|
if yield_index
yield item, i
else
yield item
end
end
end
end
end