refactor: simplify pagination helper

* get rid of PaginationRenderer
* move Paginator to main helpers file
This commit is contained in:
Akira Matsuda 2011-02-27 23:25:16 +09:00
parent 6411476ff6
commit bfb09e61ad
5 changed files with 125 additions and 124 deletions

View File

@ -18,7 +18,7 @@ module Kaminari
# * <tt>:remote</tt> - Ajax? (false by default)
# * <tt>:ANY_OTHER_VALUES</tt> - Any other hash key & values would be directly passed into each tag as :locals value.
def paginate(scope, options = {}, &block)
Kaminari::Helpers::PaginationRenderer.new self, options.reverse_merge(:current_page => scope.current_page, :num_pages => scope.num_pages, :per_page => scope.limit_value, :param_name => :page, :remote => false)
Kaminari::Helpers::Paginator.new self, options.reverse_merge(:current_page => scope.current_page, :num_pages => scope.num_pages, :per_page => scope.limit_value, :param_name => :page, :remote => false)
end
end
end

View File

@ -2,15 +2,48 @@ require File.join(File.dirname(__FILE__), 'tags')
module Kaminari
module Helpers
# The main class that controlls the whole process
class PaginationRenderer
# The main container tag
class Paginator < Tag
def initialize(template, options) #:nodoc:
@window_options = {}.tap do |h|
h[:window] = options.delete(:window) || options.delete(:inner_window) || 4
outer_window = options.delete(:outer_window)
h[:left] = options.delete(:left) || outer_window || 0
h[:right] = options.delete(:right) || outer_window || 0
end
@template, @options = template, options
# so that this instance can actually "render". Black magic?
@output_buffer = ActionView::OutputBuffer.new
end
# render given block as a view template
def render(&block)
instance_eval &block if @options[:num_pages] > 1
@output_buffer
end
# enumerate each page providing PageProxy object as the block parameter
def each_page
1.upto(@options[:num_pages]) do |i|
yield PageProxy.new(@window_options.merge(@options), i, @last)
end
end
def page_tag(page)
@last = Page.new @template, @options.merge(:page => page)
end
%w[first_page prev_page next_page last_page gap].each do |tag|
eval <<-DEF
def #{tag}_tag
@last = #{tag.classify}.new @template, @options
end
DEF
end
def to_s #:nodoc:
suppress_logging_render_partial do
Paginator.new(@template, @options).to_s
super @window_options.merge(@options).merge :paginator => self
end
end
@ -33,6 +66,77 @@ module Kaminari
blk.call
end
end
# Wraps a "page number" and provides some utility methods
class PageProxy
include Comparable
def initialize(options, page, last) #:nodoc:
@options, @page, @last = options, page, last
end
# the page number
def number
@page
end
# current page or not
def current?
@page == @options[:current_page]
end
# the first page or not
def first?
@page == 1
end
# the last page or not
def last?
@page == @options[:num_pages]
end
# the previous page or not
def prev?
@page == @options[:current_page] - 1
end
# the next page or not
def next?
@page == @options[:current_page] + 1
end
# within the left outer window or not
def left_outer?
@page <= @options[:left]
end
# within the right outer window or not
def right_outer?
@options[:num_pages] - @page < @options[:right]
end
# inside the inner window or not
def inside_window?
(@page - @options[:current_page]).abs <= @options[:window]
end
# The last rendered tag was "truncated" or not
def was_truncated?
@last.is_a? Gap
end
def to_i
number
end
def to_s
number.to_s
end
def <=>(other)
to_i <=> other.to_i
end
end
end
end
end

View File

@ -28,121 +28,6 @@ module Kaminari
end
end
# The container tag
class Paginator < Tag
def initialize(template, options) #:nodoc:
@window_options = {}.tap do |h|
h[:window] = options.delete(:window) || options.delete(:inner_window) || 4
outer_window = options.delete(:outer_window)
h[:left] = options.delete(:left) || outer_window || 0
h[:right] = options.delete(:right) || outer_window || 0
end
@template, @options = template, options
# so that this instance can actually "render". Black magic?
@output_buffer = ActionView::OutputBuffer.new
end
# render given block as a view template
def render(&block)
instance_eval &block if @options[:num_pages] > 1
@output_buffer
end
# enumerate each page providing PageProxy object as the block parameter
def each_page
1.upto(@options[:num_pages]) do |i|
yield PageProxy.new(@window_options.merge(@options), i, @last)
end
end
def page_tag(page)
@last = Page.new @template, @options.merge(:page => page)
end
%w[first_page prev_page next_page last_page gap].each do |tag|
eval <<-DEF
def #{tag}_tag
@last = #{tag.classify}.new @template, @options
end
DEF
end
def to_s #:nodoc:
super @window_options.merge(@options).merge :paginator => self
end
# Wraps a "page number" and provides some utility methods
class PageProxy
include Comparable
def initialize(options, page, last) #:nodoc:
@options, @page, @last = options, page, last
end
# the page number
def number
@page
end
# current page or not
def current?
@page == @options[:current_page]
end
# the first page or not
def first?
@page == 1
end
# the last page or not
def last?
@page == @options[:num_pages]
end
# the previous page or not
def prev?
@page == @options[:current_page] - 1
end
# the next page or not
def next?
@page == @options[:current_page] + 1
end
# within the left outer window or not
def left_outer?
@page <= @options[:left]
end
# within the right outer window or not
def right_outer?
@options[:num_pages] - @page < @options[:right]
end
# inside the inner window or not
def inside_window?
(@page - @options[:current_page]).abs <= @options[:window]
end
# The last rendered tag was "truncated" or not
def was_truncated?
@last.is_a? Gap
end
def to_i
number
end
def to_s
number.to_s
end
def <=>(other)
to_i <=> other.to_i
end
end
end
# Tag that contains a link
module Link
# target page number

View File

@ -1,11 +1,12 @@
require File.expand_path('../spec_helper', File.dirname(__FILE__))
include Kaminari::Helpers
describe 'Kaminari::Helpers::PaginationRenderer' do
describe 'Kaminari::Helpers::Paginator' do
let :template do
stub(r = Object.new) do
render.with_any_args
params { {} }
options { {} }
url_for {|h| "/foo?page=#{h[:page]}"}
end
r
@ -13,10 +14,18 @@ describe 'Kaminari::Helpers::PaginationRenderer' do
describe '#params' do
before do
@renderer = PaginationRenderer.new(template, :params => {:controller => 'foo', :action => 'bar'})
@paginator = Paginator.new(template, :params => {:controller => 'foo', :action => 'bar'})
end
subject { @renderer.instance_variable_get '@template' }
its(:params) { should == {:controller => 'foo', :action => 'bar'} }
subject { @paginator.page_tag(template).instance_variable_get('@params') }
it { should == {:controller => 'foo', :action => 'bar'} }
end
describe '#param_name' do
before do
@paginator = Paginator.new(template, :param_name => :pagina)
end
subject { @paginator.page_tag(template).instance_variable_get('@param_name') }
it { should == :pagina }
end
#TODO test somehow...

View File

@ -121,7 +121,10 @@ describe 'Kaminari::Helpers' do
end
describe '#was_truncated?' do
before do
stub(@template = Object.new).options { {} }
stub(@template = Object.new) do
options { {} }
params { {} }
end
end
context 'last.is_a? Gap' do
subject { Paginator::PageProxy.new({}, 10, Gap.new(@template)) }