Refactored pagination into search method, Sweet syntax is now in Compat
Andy Grundman [Sun, 28 Aug 2005 02:19:12 +0000 (02:19 +0000)]
MANIFEST
lib/DBIx/Class/CDBICompat.pm
lib/DBIx/Class/CDBICompat/Pager.pm [new file with mode: 0644]
lib/DBIx/Class/Core.pm
lib/DBIx/Class/Pager.pm [deleted file]
lib/DBIx/Class/ResultSet.pm
lib/DBIx/Class/Table.pm
t/07pager.t
t/cdbi-t/30-pager.t [new file with mode: 0644]

index 33213a9..be95530 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -19,6 +19,7 @@ lib/DBIx/Class/CDBICompat/LazyLoading.pm
 lib/DBIx/Class/CDBICompat/LiveObjectIndex.pm
 lib/DBIx/Class/CDBICompat/MightHave.pm
 lib/DBIx/Class/CDBICompat/ObjIndexStubs.pm
+lib/DBIx/Class/CDBICompat/Pager.pm
 lib/DBIx/Class/CDBICompat/ReadOnly.pm
 lib/DBIx/Class/CDBICompat/Retrieve.pm
 lib/DBIx/Class/CDBICompat/Stringify.pm
@@ -58,6 +59,7 @@ t/03podcoverage.t
 t/04db.t
 t/05multipk.t
 t/06relationship.t
+t/07pager.t
 t/08inflate.t
 t/08inflate_has_a.t
 t/09update.t
@@ -83,6 +85,7 @@ t/cdbi-t/16-reserved.t
 t/cdbi-t/18-has_a.t
 t/cdbi-t/19-set_sql.t
 t/cdbi-t/21-iterator.t
+t/cdbi-t/30-pager.t
 t/cdbi-t/98-failure.t
 t/lib/DBICTest.pm
 t/lib/DBICTest/Schema.pm
index 08bc7c9..c221a61 100644 (file)
@@ -23,6 +23,7 @@ __PACKAGE__->load_own_components(qw/
   AutoUpdate
   TempColumns
   Retrieve
+  Pager
   ColumnGroups
   ImaDBI/);
 
diff --git a/lib/DBIx/Class/CDBICompat/Pager.pm b/lib/DBIx/Class/CDBICompat/Pager.pm
new file mode 100644 (file)
index 0000000..cd01047
--- /dev/null
@@ -0,0 +1,16 @@
+package DBIx::Class::CDBICompat::Pager;\r
+\r
+use strict;\r
+use warnings FATAL => 'all';\r
+\r
+*pager = \&page;\r
+\r
+sub page {\r
+  my $class = shift;\r
+\r
+  my $it = $class->search(@_);\r
+  my $pager = $class->_page_object;\r
+  return ( $pager, $it );\r
+}\r
+\r
+1;\r
index b1d95fa..5dc4096 100644 (file)
@@ -9,7 +9,6 @@ use base qw/DBIx::Class/;
 __PACKAGE__->load_components(qw/
   InflateColumn
   Relationship
-  Pager
   PK
   Row
   Table
diff --git a/lib/DBIx/Class/Pager.pm b/lib/DBIx/Class/Pager.pm
deleted file mode 100644 (file)
index 1d715da..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-package DBIx::Class::Pager;
-
-use strict;
-use warnings;
-
-use NEXT;
-use Data::Page;
-
-=head1 NAME 
-
-DBIx::Class::Pager -  Pagination of resultsets
-
-=head1 SYNOPSIS
-
-=head1 DESCRIPTION
-
-This class lets you page through a resultset.
-
-=head1 METHODS
-
-=over 4
-
-=item page
-
-=item pager
-
-=cut
-
-*pager = \&page;
-
-sub page {
-  my $self = shift;
-  my ($criteria, $attr) = @_;
-  
-  my $rows    = $attr->{rows} || 10;
-  my $current = $attr->{page} || 1;
-  
-  # count must not use LIMIT, so strip out rows/offset
-  delete $attr->{$_} for qw/rows offset/;
-  
-  my $total = $self->count( $criteria, $attr );
-  my $page = Data::Page->new( $total, $rows, $current );
-  
-  $attr->{rows}   = $page->entries_per_page;
-  $attr->{offset} = $page->skipped;
-
-  my $iterator = $self->search( $criteria, $attr );
-
-  return ( $page, $iterator );
-}
-
-1;
-
-=back
-
-=head1 AUTHORS
-
-Andy Grundman <andy@hybridized.org>
-
-=head1 LICENSE
-
-You may distribute this code under the same terms as Perl itself.
-
-=cut
-
index 3f8403d..72ea52f 100644 (file)
@@ -49,9 +49,9 @@ sub count {
   my ($self) = @_;
   my $db_class = $self->{class};
 
-  # offset breaks COUNT(*), so remove it
+  # offset and order by are not needed to count
   my $attrs = { %{ $self->{attrs} } };
-  delete $attrs->{offset};
+  delete $attrs->{$_} for qw/offset order_by/;
       
   my @cols = 'COUNT(*)';
   my ($c) = $db_class->storage->select_single($db_class->_table_name, \@cols,
index 9aa00ab..451b0bd 100644 (file)
@@ -4,6 +4,7 @@ use strict;
 use warnings;
 
 use DBIx::Class::ResultSet;
+use Data::Page;
 
 use base qw/Class::Data::Inheritable/;
 
@@ -15,6 +16,8 @@ __PACKAGE__->mk_classdata('table_alias'); # FIXME: Doesn't actually do anything
 
 __PACKAGE__->mk_classdata('_resultset_class' => 'DBIx::Class::ResultSet');
 
+__PACKAGE__->mk_classdata('_page_object');
+
 sub iterator_class { shift->_resultset_class(@_) }
 
 =head1 NAME 
@@ -112,9 +115,26 @@ sub search {
     $attrs = { %{ pop(@_) } };
   }
   $attrs->{where} = (@_ == 1 || ref $_[0] eq "HASH" ? shift: {@_});
+  
+  # for pagination, we create the resultset with no limit and slice it later
+  my $page = {};
+  if ( $attrs->{page} ) {
+    map { $page->{$_} = $attrs->{$_} } qw/rows page/;
+    delete $attrs->{$_} for qw/rows offset page/;
+  }
 
   my $rs = $class->resultset($attrs);
-
+  
+  if ( $page->{page} ) {
+    my $pager = Data::Page->new( 
+      $rs->count, 
+      $page->{rows} || 10, 
+      $page->{page} || 1 );
+    $class->_page_object( $pager );
+    return $rs->slice( $pager->skipped,
+      $pager->skipped + $pager->entries_per_page - 1 );
+  }
+  
   return (wantarray ? $rs->all : $rs);
 }
 
@@ -175,6 +195,17 @@ sub find_or_create {
 
 sub columns { return keys %{shift->_columns}; }
 
+=item page
+
+  $pager = $class->page;
+  
+Returns a Data::Page object for the most recent search that was performed
+using the page parameter.
+
+=cut
+
+sub page { shift->_page_object }
+
 1;
 
 =back
index 38a290a..04b8b28 100644 (file)
@@ -7,13 +7,14 @@ use lib qw(t/lib);
 use_ok('DBICTest');
 
 # first page
-my ( $pager, $it ) = DBICTest::CD->page(
+my $it = DBICTest::CD->search(
     {},
     { order_by => 'title',
       rows => 3,
       page => 1 }
 );
-      
+my $pager = DBICTest::CD->page;
+
 is( $pager->entries_on_this_page, 3, "entries_on_this_page ok" );
 
 is( $pager->next_page, 2, "next_page ok" );
@@ -25,38 +26,22 @@ $it->next;
 
 is( $it->next, undef, "next past end of page ok" );
 
-# second page
-( $pager, $it ) = DBICTest::CD->page( 
+# second page, testing with array 
+my @page2 = DBICTest::CD->search( 
     {},
     { order_by => 'title',
       rows => 3,
       page => 2 }
 );
+$pager = DBICTest::CD->page;
 
 is( $pager->entries_on_this_page, 2, "entries on second page ok" );
 
-is( $it->next->title, "Generic Manufactured Singles", "second page first title ok" );
-
-# XXX: Should we support disable_sql_paging?
-#( $pager, $it ) = DBICTest::CD->page(
-#    {},
-#    { rows => 2,
-#      page => 2,
-#      disable_sql_paging => 1 } );
-#
-#cmp_ok( $pager->total_entries, '==', 5, "disable_sql_paging total_entries ok" );
-#
-#cmp_ok( $pager->previous_page, '==', 1, "disable_sql_paging previous_page ok" );
-#
-#is( $it->next->title, "Caterwaulin' Blues", "disable_sql_paging iterator->next ok" );
-#
-#$it->next;
-#
-#is( $it->next, undef, "disable_sql_paging next past end of page ok" );
+is( $page2[0]->title, "Generic Manufactured Singles", "second page first title ok" );
 
 # based on a failing criteria submitted by waswas
 # requires SQL::Abstract >= 1.20
-( $pager, $it ) = DBICTest::CD->page(
+$it = DBICTest::CD->search(
     { title => [
         -and => 
             {
diff --git a/t/cdbi-t/30-pager.t b/t/cdbi-t/30-pager.t
new file mode 100644 (file)
index 0000000..aba18e0
--- /dev/null
@@ -0,0 +1,47 @@
+use strict;\r
+use Test::More;\r
+\r
+BEGIN {\r
+       eval "use DBD::SQLite";\r
+       plan $@ ? (skip_all => 'needs DBD::SQLite for testing') : (tests => 6);\r
+}\r
+\r
+use lib 't/testlib';\r
+use Film;\r
+\r
+my @film  = (\r
+       Film->create({ Title => 'Film 1' }),\r
+       Film->create({ Title => 'Film 2' }),\r
+       Film->create({ Title => 'Film 3' }),\r
+       Film->create({ Title => 'Film 4' }),\r
+       Film->create({ Title => 'Film 5' }),\r
+);\r
+\r
+# first page\r
+my ( $pager, $it ) = Film->page(\r
+    {},\r
+    { rows => 3,\r
+      page => 1 }\r
+);\r
+\r
+is( $pager->entries_on_this_page, 3, "entries_on_this_page ok" );\r
+\r
+is( $pager->next_page, 2, "next_page ok" );\r
+\r
+is( $it->next->title, "Film 1", "iterator->next ok" );\r
+\r
+$it->next;\r
+$it->next;\r
+\r
+is( $it->next, undef, "next past end of page ok" );\r
+\r
+# second page\r
+( $pager, $it ) = Film->page( \r
+    {},\r
+    { rows => 3,\r
+      page => 2 }\r
+);\r
+\r
+is( $pager->entries_on_this_page, 2, "entries on second page ok" );\r
+\r
+is( $it->next->title, "Film 4", "second page first title ok" );\r