Skip to content
Browse files

updates to allow for multiple pagers on the same page

  • Loading branch information...
1 parent b9e7d5b commit c1ba96ef7549f809c509eff125f6603720c378b8 @hassox hassox committed
Showing with 115 additions and 102 deletions.
  1. +4 −3 lib/dm-pager/defaults.rb
  2. +49 −48 lib/dm-pager/pager.rb
  3. +17 −14 lib/dm-pager/pagination.rb
  4. +45 −37 spec/unit/pager_spec.rb
View
7 lib/dm-pager/defaults.rb
@@ -10,7 +10,8 @@ module Pagination
:next_text => 'Next',
:first_text => 'First',
:last_text => 'Last',
- :more_text => '...'
+ :more_text => '...',
+ :page_param => :page
}
##
@@ -31,10 +32,10 @@ module Pagination
#
# DataMapper::Pagination.defaults[:size] = 5
#
-
+
def self.defaults
@defaults
end
end
-end
+end
View
97 lib/dm-pager/pager.rb
@@ -1,52 +1,53 @@
module DataMapper
class Pager
-
+
##
# Total number of un-limited records.
-
- attr_reader :total
-
+
+ attr_reader :total
+
##
# Records per page.
-
- attr_reader :per_page
-
+
+ attr_reader :per_page
+
##
# Current page number.
-
+
attr_reader :current_page
-
+
##
# Previous page or nil when no previous page is available.
-
+
attr_reader :previous_page
-
+
##
# Next page or nil when no more pages are available.
-
+
attr_reader :next_page
-
+
##
# Total number of pages.
-
+
attr_reader :total_pages
-
+
##
# Initialize with _options_.
-
+
def initialize options = {}
+ @page_param = options.delete(:page_param) || :page
@total = options.delete :total
@per_page = options.delete :limit
- @current_page = options.delete :page
+ @current_page = options.delete @page_param
@total_pages = total.quo(per_page).ceil
@next_page = current_page + 1 unless current_page >= total_pages
@previous_page = current_page - 1 unless current_page <= 1
end
-
+
##
# Render the pager with the given _uri_ and _options_.
- #
+ #
# === Examples
#
# User.page(2).pager.to_html('/users')
@@ -56,7 +57,7 @@ def initialize options = {}
#
# :size Number of intermediate page number links to be shown; Defaults to 7
#
-
+
def to_html uri, options = {}
return unless total_pages > 1
@uri, @options = uri, options
@@ -73,36 +74,36 @@ def to_html uri, options = {}
last_link,
'</ul>'].join
end
-
+
private
-
+
##
# Fetch _key_ from the options passed to #to_html, or
# its default value.
-
+
def option key
@options.fetch key, Pagination.defaults[key]
end
-
+
##
- # Link to _page_ with optional anchor tag _contents_.
-
+ # Link to _page_ with optional anchor tag _contents_.
+
def link_to page, contents = nil
%(<a href="#{uri_for(page)}">#{contents || page}</a>)
end
-
+
##
# More pages indicator for _position_.
-
+
def more position
return '' if position == :before && (current_page <= 1 || first <= 1)
return '' if position == :after && (current_page >= total_pages || last >= total_pages)
li 'more', option(:more_text)
end
-
+
##
# Intermediate page links array.
-
+
def intermediate_links
(first..last).map do |page|
classes = ["page-#{page}"]
@@ -110,35 +111,35 @@ def intermediate_links
li classes.join(' '), link_to(page)
end
end
-
+
##
# Previous link.
-
+
def previous_link
li 'previous jump', link_to(previous_page, option(:previous_text)) if previous_page
end
-
+
##
# Next link.
-
+
def next_link
li 'next jump', link_to(next_page, option(:next_text)) if next_page
end
-
+
##
# Last link.
-
+
def last_link
li 'last jump', link_to(total_pages, option(:last_text)) if next_page
end
-
+
##
# First link.
-
+
def first_link
li 'first jump', link_to(1, option(:first_text)) if previous_page
end
-
+
##
# Determine first intermediate page.
@@ -151,7 +152,7 @@ def first
first
end
end
-
+
##
# Determine last intermediate page.
@@ -164,14 +165,14 @@ def last
last
end
end
-
+
##
# Renders a <li> with the given _css_class_ and _contents_.
-
+
def li css_class = nil, contents = nil
"<li#{%( class="#{css_class}") if css_class}>#{contents}</li>\n"
end
-
+
##
# Uri for _page_. The following conversions are made
# to the _uri_ previously passed to #to_html:
@@ -183,11 +184,11 @@ def li css_class = nil, contents = nil
def uri_for page
case @uri
- when /\bpage=/ ; @uri.gsub /\bpage=\d+/, "page=#{page}"
- when /\?/ ; @uri += "&page=#{page}"
- else ; @uri += "?page=#{page}"
+ when /\b#{@page_param}=/ ; @uri.gsub /\b#{@page_param}=\d+/, "#{@page_param}=#{page}"
+ when /\?/ ; @uri += "&#{@page_param}=#{page}"
+ else ; @uri += "?#{@page_param}=#{page}"
end
end
-
+
end
-end
+end
View
31 lib/dm-pager/pagination.rb
@@ -1,16 +1,16 @@
module DataMapper
module Pagination
-
+
##
# DataMapper::Pager instance.
-
+
attr_accessor :pager
-
+
##
# Page collection by the _page_ number and _options_ provided.
#
- # Since pagers will commonly be used with query strings, we
+ # Since pagers will commonly be used with query strings, we
# coerce all numeric strings such as '12' to their integer value 12.
# This is the case for _page_, :per_page, :page, etc.
#
@@ -19,21 +19,24 @@ module Pagination
# :page Current page number
# :per_page Results per page; defaults to 6
# :order Defaults to [:id.desc]
+ # :page_param The paramter to use to encode the page. Default :page
#
# === Examples
- #
+ #
# User.all.page
# User.all.page(2)
# User.all.page(2, :per_page => 5)
# User.all.page(:page => 2, :per_page => 5)
+ # User.all.page(:page => 2, :page_param => :user_page)
#
-
+
def page page = nil, options = {}
options, page = page, nil if page.is_a? Hash
- page ||= pager_option :page, options
- options.delete :page
+ page_param = pager_option(:page_param, options)
+ page ||= pager_option page_param, options
+ options.delete page_param
page = 1 unless (page = page.to_i) && page > 1
- per_page = pager_option(:per_page, options).to_i
+ per_page = pager_option(:per_page, options).to_i
query = options.dup
collection = new_collection scoped_query(options = {
:limit => per_page,
@@ -41,22 +44,22 @@ def page page = nil, options = {}
:order => [:id.desc]
}.merge(query))
query.delete :order
- options.merge! :total => count(query), :page => page
+ options.merge! :total => count(query), page_param => page, :page_param => page_param
collection.pager = DataMapper::Pager.new options
collection
end
-
+
private
-
+
##
# Return value for _key_ from indifferent hash _options_.
- #
+ #
# * Checks for sym key
# * Checks for string key
# * Checks DataMapper::Pagination.defaults for the sym key
# * Deletes both keys to prevent them from being part of the query
#
-
+
def pager_option key, options = {}
a = options.delete key.to_sym
b = options.delete key.to_s
View
82 spec/unit/pager_spec.rb
@@ -3,58 +3,66 @@
describe DataMapper::Pager do
before(:each) { mock_items }
-
+
describe "#to_html" do
describe "when pages are available" do
it "should render a ul.pager wrapper" do
- Item.page.pager.to_html('/').should match(/ul class="([^"]+)?"/)
+ begin
+ Item.page.pager.to_html('/').should match(/ul class="([^"]+)?"/)
+ rescue =>e
+ puts e.class, e.message, e.backtrace.join("\n")
+ end
end
-
+
it "should render a ul containing intermediate items" do
Item.page.pager.to_html('/').should match(/<ul class="[^"]+?"><li/)
end
-
+
it "should add the 'active' class to the current page link <li>" do
Item.page.pager.to_html('/').should include('li class="page-1 active"><a href="/?page=1"')
Item.page(2).pager.to_html('/').should include('li class="page-2 active"><a href="/?page=2"')
Item.page(3).pager.to_html('/').should include('li class="page-3 active"><a href="/?page=3"')
end
-
+
it "should add li.last.jump" do
Item.page.pager.to_html('/').should include('<li class="last jump">')
end
-
+
it "should add li.first.jump" do
Item.page(2).pager.to_html('/').should include('<li class="first jump"')
end
-
+
it "should add li.next.jump" do
Item.page.pager.to_html('/').should include('<li class="next jump">')
end
-
+
it "should add li.previous.jump" do
Item.page(2).pager.to_html('/').should include('<li class="previous jump">')
end
+
+ it "should allow setting the paging parameter name" do
+ Item.page(2, :page_param => :hot_stuff).pager.to_html("/items").should include("href=\"/items?hot_stuff=2\"")
+ end
end
-
+
describe "when one page is available" do
it "should render nothing" do
Item.all(:id.lt => 2).page.pager.to_html('/').should be_nil
end
end
-
+
describe "when no pages are available" do
it "should render nothing" do
Item.all(:id.lt => 1).page.pager.to_html('/').should be_nil
end
end
-
+
describe "when on the first page" do
it "should not render the 'Previous' page link" do
markup = Item.page.pager.to_html('/')
markup.should_not include('Previous')
end
-
+
it "should render some intermediate page links with ... after" do
markup = Item.page.pager.to_html('/', :size => 3)
markup.should include('>1<')
@@ -63,28 +71,28 @@
markup.should_not include('>4<')
markup.should include(%(<li class="more">...</li>\n<li class="next jump"))
end
-
+
it "should not render ... before" do
markup = Item.page.pager.to_html('/', :size => 3)
markup.should_not include('<a href="/?page=3" class="previous jump">Previous</a><li class="more">...</li>')
end
-
+
it "should not render the 'First' page link" do
markup = Item.page.pager.to_html('/')
markup.should_not include('First')
end
-
+
it "should render the 'Last' page link" do
markup = Item.page.pager.to_html('/')
markup.should include('Last')
end
end
-
+
describe "with the :size option set" do
it "should raise an error when given an even number" do
lambda { Item.page.pager.to_html('/', :size => 2) }.should raise_error(ArgumentError, /must be an odd number/)
end
-
+
it "should render only the specified number of intermediate page links" do
markup = Item.page.pager.to_html('/', :size => 3)
markup.should include('>1<')
@@ -93,7 +101,7 @@
markup.should_not include('>4<')
end
end
-
+
[:first, :previous, :next, :last].each do |pos|
describe "with the #{pos.inspect} option set" do
it "should change the default contents for the '#{pos}' link" do
@@ -102,23 +110,23 @@
end
end
end
-
+
describe "when on the last page" do
it "should not render the 'Next' page link" do
markup = Item.page(4).pager.to_html('/')
markup.should_not include('Next')
end
-
+
it "should not render the 'Last' page link" do
markup = Item.page(4).pager.to_html('/')
markup.should_not include('Last')
end
-
+
it "should render the 'First' page link" do
markup = Item.page(4).pager.to_html('/')
markup.should include('First')
end
-
+
it "should render some intermediate page links with ... before" do
markup = Item.page(4).pager.to_html('/', :size => 3)
markup.should include(%(<li class="previous jump"><a href="/?page=3">Previous</a></li>\n<li class="more">...<))
@@ -128,24 +136,24 @@
markup.should include('>4<')
markup.should_not include('>5<')
end
-
+
it "should not render ... after" do
markup = Item.page(4).pager.to_html('/', :size => 3)
markup.should_not include(%(<li class="more">...</li>\n<a href="/?page=6" class="next jump"))
end
end
-
+
describe "when on an intermediate page" do
it "should render the 'Previous' page link" do
markup = Item.page(2).pager.to_html('/')
markup.should include('Previous')
end
-
+
it "should render the 'Next' page link" do
- markup = Item.page(2).pager.to_html('/')
+ markup = Item.page(2).pager.to_html('/')
markup.should include('Next')
end
-
+
it "should render some intermediate page links with ... before and after" do
markup = Item.page(5, :per_page => 2).pager.to_html('/', :size => 3)
markup.should include(%(<li class="previous jump"><a href="/?page=4">Previous</a></li>\n<li class="more">...</li>))
@@ -156,18 +164,18 @@
markup.should_not include('>7<')
markup.should include(%(<li class="more">...</li>\n<li class="next jump"))
end
-
+
it "should render the 'Last' page link" do
markup = Item.page(2).pager.to_html('/')
markup.should include('Last')
end
-
+
it "should render the 'First' page link" do
markup = Item.page(2).pager.to_html('/')
markup.should include('First')
end
end
-
+
describe "when on the second page" do
it "should render 1 through 3 when :size is 3 followed by ..." do
markup = Item.page(2, :per_page => 2).pager.to_html('/', :size => 3)
@@ -179,7 +187,7 @@
markup.should include(%(<li class="more">...</li>\n<li class="next jump"))
end
end
-
+
describe "when on the second last page" do
it "should render 8 through 10 when :size is 3 with preceding ..." do
markup = Item.page(9, :per_page => 2).pager.to_html('/', :size => 3)
@@ -192,14 +200,14 @@
markup.should_not include(%(<li class="more">...</li>\n<li class="next jump"))
end
end
-
+
describe "when passing a uri without a query string" do
it "should append a query string to each uri" do
markup = Item.page.pager.to_html 'items'
markup.should include('items?page=1')
end
end
-
+
describe "when passing a uri with a query string" do
describe "containing page=N" do
it "should alter the page value" do
@@ -207,14 +215,14 @@
markup.should include('items?page=1')
end
end
-
+
describe "not containing page=N" do
it "should append a pair" do
markup = Item.page.pager.to_html 'items?foo=bar'
markup.should include('items?foo=bar&page=1')
end
end
-
+
describe "when containing other keys with 'page'" do
it "should append a pair" do
markup = Item.page.pager.to_html 'items?per_page=5'
@@ -224,6 +232,6 @@
end
end
end
-
+
end
-end
+end

0 comments on commit c1ba96e

Please sign in to comment.
Something went wrong with that request. Please try again.