From bfb09e61ad75051aa8dbc1f518a03a5c40656d45 Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Sun, 27 Feb 2011 23:25:16 +0900 Subject: [PATCH] refactor: simplify pagination helper * get rid of PaginationRenderer * move Paginator to main helpers file --- lib/kaminari/helpers/action_view_extension.rb | 2 +- lib/kaminari/helpers/helpers.rb | 110 ++++++++++++++++- lib/kaminari/helpers/tags.rb | 115 ------------------ spec/helpers/helpers_spec.rb | 17 ++- spec/helpers/tags_spec.rb | 5 +- 5 files changed, 125 insertions(+), 124 deletions(-) diff --git a/lib/kaminari/helpers/action_view_extension.rb b/lib/kaminari/helpers/action_view_extension.rb index c9c89d2..9cdf7f0 100644 --- a/lib/kaminari/helpers/action_view_extension.rb +++ b/lib/kaminari/helpers/action_view_extension.rb @@ -18,7 +18,7 @@ module Kaminari # * :remote - Ajax? (false by default) # * :ANY_OTHER_VALUES - 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 diff --git a/lib/kaminari/helpers/helpers.rb b/lib/kaminari/helpers/helpers.rb index bc52011..d6d0419 100644 --- a/lib/kaminari/helpers/helpers.rb +++ b/lib/kaminari/helpers/helpers.rb @@ -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 diff --git a/lib/kaminari/helpers/tags.rb b/lib/kaminari/helpers/tags.rb index c78860d..8b9ab3a 100644 --- a/lib/kaminari/helpers/tags.rb +++ b/lib/kaminari/helpers/tags.rb @@ -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 diff --git a/spec/helpers/helpers_spec.rb b/spec/helpers/helpers_spec.rb index 3601576..f89c055 100644 --- a/spec/helpers/helpers_spec.rb +++ b/spec/helpers/helpers_spec.rb @@ -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... diff --git a/spec/helpers/tags_spec.rb b/spec/helpers/tags_spec.rb index 5049b05..95393e0 100644 --- a/spec/helpers/tags_spec.rb +++ b/spec/helpers/tags_spec.rb @@ -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)) }