New collection_column feature with working tests.
Aran Deltac [Thu, 23 Mar 2006 19:57:43 +0000 (19:57 +0000)]
lib/DBIx/Class/Positioned.pm
t/lib/DBICTest/Schema/Employee/Positioned.pm
t/lib/sqlite.sql
t/run/26positioned.tl

index 02d4aac..03d4156 100644 (file)
@@ -17,6 +17,7 @@ Create a table for your positionable data.
     name TEXT NOT NULL,
     position INTEGER NOT NULL
   );
+  # Optional: group_id INTEGER NOT NULL
 
 In your Schema or DB class add Positioned to the top 
 of the component list.
@@ -28,6 +29,7 @@ each row.
 
   package My::Employee;
   __PACKAGE__->position_column('position');
+  __PACKAGE__->collection_column('group_id'); # optional
 
 Thats it, now you can change the position of your objects.
 
@@ -35,6 +37,8 @@ Thats it, now you can change the position of your objects.
   use My::Employee;
   
   my $employee = My::Employee->create({ name=>'Matt S. Trout' });
+  # If using collection_column:
+  my $employee = My::Employee->create({ name=>'Matt S. Trout', group_id=>1 });
   
   my $rs = $employee->siblings();
   my @siblings = $employee->siblings();
@@ -335,7 +339,7 @@ defined then this will return an empty list.
 =cut
 
 sub _collection_clause {
-    my $self = shift;
+    my( $self ) = @_;
     if ($self->collection_column()) {
         return ( $self->collection_column() => $self->get_column($self->collection_column()) );
     }
index da7444e..3ce5744 100644 (file)
@@ -15,6 +15,10 @@ __PACKAGE__->add_columns(
     position => {
         data_type => 'integer',
     },
+    group_id => {
+        data_type => 'integer',
+        is_nullable => 1,
+    },
     name => {
         data_type => 'varchar',
         size      => 100,
@@ -28,6 +32,7 @@ __PACKAGE__->position_column('position');
 __PACKAGE__->mk_classdata('field_name_for', {
     employee_id => 'primary key',
     position    => 'list position',
+    group_id    => 'collection column',
     name        => 'employee name',
 });
 
index 6cd3abe..c7190e9 100644 (file)
@@ -1,6 +1,6 @@
 -- 
 -- Created by SQL::Translator::Producer::SQLite
--- Created on Tue Mar 21 12:11:03 2006
+-- Created on Thu Mar 23 11:13:18 2006
 -- 
 BEGIN TRANSACTION;
 
@@ -10,6 +10,7 @@ BEGIN TRANSACTION;
 CREATE TABLE employees_positioned (
   employee_id INTEGER PRIMARY KEY NOT NULL,
   position integer NOT NULL,
+  group_id integer,
   name varchar(100)
 );
 
index 720b173..224e658 100644 (file)
@@ -2,7 +2,7 @@
 
 sub run_tests {
 
-    plan tests => 66;
+    plan tests => 321;
     my $schema = shift;
 
     my $employees = $schema->resultset('Employee::Positioned');
@@ -12,64 +12,87 @@ sub run_tests {
         $employees->create({ name=>'temp' });
     }
     $employees = $employees->search(undef,{order_by=>'position'});
-    ok( check_positions($employees), "$class: intial positions" );
+    ok( check_rs($employees), "intial positions" );
 
+    hammer_rs( $employees );
+
+    DBICTest::Employee::Positioned->collection_column('group_id');
+    $employees->delete();
+    foreach my $group_id (1..3) {
+        foreach (1..6) {
+            $employees->create({ name=>'temp', group_id=>$group_id });
+        }
+    }
+    $employees = $employees->search(undef,{order_by=>'group_id,position'});
+
+    foreach my $group_id (1..3) {
+        my $group_employees = $employees->search({group_id=>$group_id});
+        $group_employees->all();
+        ok( check_rs($group_employees), "group intial positions" );
+        hammer_rs( $group_employees );
+    }
+
+}
+
+sub hammer_rs {
+    my $rs = shift;
     my $employee;
+    my $count = $rs->count();
+    my $position_column = $rs->result_class->position_column();
 
-    foreach my $position (1..$employees->count()) {
+    foreach my $position (1..$count) {
 
-        $employee = $employees->find({ position=>$position });
-        $employee->move_previous();
-        ok( check_positions($employees), "$class: move_previous( $position )" );
+        $row = $rs->find({ $position_column=>$position });
+        $row->move_previous();
+        ok( check_rs($rs), "move_previous( $position )" );
 
-        $employee = $employees->find({ position=>$position });
-        $employee->move_next();
-        ok( check_positions($employees), "$class: move_next( $position )" );
+        $row = $rs->find({ $position_column=>$position });
+        $row->move_next();
+        ok( check_rs($rs), "move_next( $position )" );
 
-        $employee = $employees->find({ position=>$position });
-        $employee->move_first();
-        ok( check_positions($employees), "$class: move_first( $position )" );
+        $row = $rs->find({ $position_column=>$position });
+        $row->move_first();
+        ok( check_rs($rs), "move_first( $position )" );
 
-        $employee = $employees->find({ position=>$position });
-        $employee->move_last();
-        ok( check_positions($employees), "$class: move_last( $position )" );
+        $row = $rs->find({ $position_column=>$position });
+        $row->move_last();
+        ok( check_rs($rs), "move_last( $position )" );
 
-        foreach my $to_position (1..$employees->count()) {
-            $employee = $employees->find({ position=>$position });
-            $employee->move_to($to_position);
-            ok( check_positions($employees), "$class: move_to( $position => $to_position )" );
+        foreach my $to_position (1..$count) {
+            $row = $rs->find({ $position_column=>$position });
+            $row->move_to($to_position);
+            ok( check_rs($rs), "move_to( $position => $to_position )" );
         }
 
-        $employee = $employees->find({ position=>$position });
+        $row = $rs->find({ position=>$position });
         if ($position==1) {
-            ok( !$employee->previous_sibling(), 'no previous sibling' );
-            ok( $employee->next_sibling(), 'next sibling' );
-            ok( !$employee->first_sibling(), 'no first sibling' );
-            ok( $employee->last_sibling(), 'last sibling' );
+            ok( !$row->previous_sibling(), 'no previous sibling' );
+            ok( !$row->first_sibling(), 'no first sibling' );
+        }
+        else {
+            ok( $row->previous_sibling(), 'previous sibling' );
+            ok( $row->first_sibling(), 'first sibling' );
         }
-        elsif ($position==$employees->count()) {
-            ok( $employee->previous_sibling(), 'previous sibling' );
-            ok( !$employee->next_sibling(), 'no next sibling' );
-            ok( $employee->first_sibling(), 'first sibling' );
-            ok( !$employee->last_sibling(), 'no last sibling' );
+        if ($position==$count) {
+            ok( !$row->next_sibling(), 'no next sibling' );
+            ok( !$row->last_sibling(), 'no last sibling' );
         }
         else {
-            ok( $employee->previous_sibling(), 'previous sibling' );
-            ok( $employee->next_sibling(), 'next sibling' );
-            ok( $employee->first_sibling(), 'first sibling' );
-            ok( $employee->last_sibling(), 'last sibling' );
+            ok( $row->next_sibling(), 'next sibling' );
+            ok( $row->last_sibling(), 'last sibling' );
         }
 
     }
 }
 
-sub check_positions {
-    my( $employees ) = @_;
-    $employees->reset();
+sub check_rs {
+    my( $rs ) = @_;
+    $rs->reset();
+    my $position_column = $rs->result_class->position_column();
     my $expected_position = 0;
-    while (my $employee = $employees->next()) {
+    while (my $row = $rs->next()) {
         $expected_position ++;
-        if ($employee->position()!=$expected_position) {
+        if ($row->get_column($position_column)!=$expected_position) {
             return 0;
         }
     }