[Catalyst-commits] r8237 - in CatalystX-CRUD/CatalystX-CRUD/trunk: . lib/CatalystX lib/CatalystX/CRUD lib/CatalystX/CRUD/Model

karpet at dev.catalyst.perl.org karpet at dev.catalyst.perl.org
Thu Aug 21 06:52:11 BST 2008


Author: karpet
Date: 2008-08-21 06:52:10 +0100 (Thu, 21 Aug 2008)
New Revision: 8237

Modified:
   CatalystX-CRUD/CatalystX-CRUD/trunk/Changes
   CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD.pm
   CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/Controller.pm
   CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/Model.pm
   CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/Model/Utils.pm
   CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/ModelAdapter.pm
Log:
add new relationship methods to core api

Modified: CatalystX-CRUD/CatalystX-CRUD/trunk/Changes
===================================================================
--- CatalystX-CRUD/CatalystX-CRUD/trunk/Changes	2008-08-20 21:50:36 UTC (rev 8236)
+++ CatalystX-CRUD/CatalystX-CRUD/trunk/Changes	2008-08-21 05:52:10 UTC (rev 8237)
@@ -134,4 +134,7 @@
 
 0.29    xxx
         * fix typos in the Tutorial
+        * add relationship methods to Controller, ModelAdapter and Model core API.
+        * added sugary alias methods for read(), update() and delete() to match CRUD.
 
+

Modified: CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/Controller.pm
===================================================================
--- CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/Controller.pm	2008-08-20 21:50:36 UTC (rev 8236)
+++ CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/Controller.pm	2008-08-21 05:52:10 UTC (rev 8237)
@@ -245,6 +245,9 @@
 Namespace for creating a new object. Calls to fetch() and edit()
 with a B<primary_key> value of C<0> (zero).
 
+B<NOTE:> This is a GET method named for consistency with the C
+in CRUD. It is not equivalent to a POST in REST terminology.
+
 =cut
 
 sub create : Local {
@@ -300,6 +303,17 @@
     $c->stash->{form}->$meth( $c->stash->{object} );
 }
 
+=head2 read
+
+Alias for view(), just for consistency with the R in CRUD.
+
+=cut
+
+sub read : PathPart Chained('fetch') Args(0) {
+    my ( $self, $c ) = @_;
+    $self->view($c);
+}
+
 =head2 save
 
 Attribute: chained to fetch(), expecting no arguments.
@@ -357,6 +371,17 @@
     1;
 }
 
+=head2 update
+
+Alias for save(), just for consistency with the U in CRUD.
+
+=cut
+
+sub update : PathPart Chained('fetch') Args(0) {
+    my ( $self, $c ) = @_;
+    $self->save($c);
+}
+
 =head2 rm
 
 Attribute: chained to fetch(), expecting no arguments.
@@ -395,6 +420,17 @@
     $self->postcommit( $c, $o );
 }
 
+=head2 delete
+
+Wrapper for rm(), just for consistency with the D in CRUD.
+
+=cut
+
+sub delete : PathPart Chained('fetch') Args(0) {
+    my ( $self, $c ) = @_;
+    $self->rm($c);
+}
+
 =head2 list
 
 Attribute: Local
@@ -455,6 +491,86 @@
     $self->do_search( $c, @arg );
 }
 
+=head2 related( I<rel_name>, I<foreign_pk_value> )
+
+Attribute: chained to fetch(), expecting two arguments.
+
+Similar to fetch(), a chain base method for add_related()
+and rm_related(). Expects two arguments: I<rel_name>
+and I<foreign_pk_value>. Those two values are put in
+stash under those key names.
+
+=cut
+
+sub related : PathPart Chained('fetch') CaptureArgs(2) {
+    my ( $self, $c, $rel, $fpk_value ) = @_;
+    return if $self->has_errors($c);
+    unless ( $self->can_write($c) ) {
+        $self->throw_error('Permission denied');
+        return;
+    }
+    if ( !$self->allow_GET_writes ) {
+        if ( $c->req->method ne 'POST' ) {
+            $self->throw_error('GET request not allowed');
+            return;
+        }
+    }
+    $c->stash->{rel_name}         = $rel;
+    $c->stash->{foreign_pk_value} = $fpk_value;
+}
+
+=head2 remove
+
+Attribute: chained to related().
+
+Dissociate a related many-to-many object of
+relationship name I<rel_name> with primary key value I<foreign_pk_value>.
+
+Example:
+
+ http://yoururl/user/123/group/456/rm_related
+
+will remove user C<123> from the group C<456>.
+
+=cut
+
+sub remove : PathPart Chained('related') Args(0) {
+    my ( $self, $c ) = @_;
+    return if $self->has_errors($c);
+    $self->do_model(
+        $c, 'rm_related', $c->stash->{object},
+        $c->stash->{rel_name},
+        $c->stash->{foreign_pk_value}
+    );
+}
+
+=head2 add
+
+Attribute: chained to related().
+
+Associate the primary object retrieved in fetch() with
+the object with I<foreign_pk_value>
+via a related many-to-many relationship I<rel_name>.
+
+Example:
+
+ http://yoururl/user/123/group/456/add_to
+
+will add user C<123> to the group C<456>.
+
+=cut
+
+sub add : PathPart Chained('related') Args(0) {
+    my ( $self, $c ) = @_;
+    return if $self->has_errors($c);
+    $self->do_model(
+        $c, 'add_related', $c->stash->{object},
+        $c->stash->{rel_name},
+        $c->stash->{foreign_pk_value}
+    );
+
+}
+
 =head1 INTERNAL METHODS
 
 The following methods are not visible via the URI namespace but

Modified: CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/Model/Utils.pm
===================================================================
--- CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/Model/Utils.pm	2008-08-20 21:50:36 UTC (rev 8236)
+++ CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/Model/Utils.pm	2008-08-21 05:52:10 UTC (rev 8237)
@@ -24,7 +24,7 @@
  
 =head1 DESCRIPTION
 
-CatalystX::CRUD::Model::Utils provides helpful not non-essential methods
+CatalystX::CRUD::Model::Utils provides helpful, non-essential methods
 for CRUD Model implementations. Stick it in your @ISA to help reduce the
 amount of code you have to write yourself.
 

Modified: CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/Model.pm
===================================================================
--- CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/Model.pm	2008-08-20 21:50:36 UTC (rev 8236)
+++ CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/Model.pm	2008-08-21 05:52:10 UTC (rev 8237)
@@ -28,11 +28,14 @@
                     );
                      
  # must define the following methods
- sub new_object { }
- sub fetch      { }
- sub search     { }
- sub iterator   { }
- sub count      { }
+ sub new_object         { }
+ sub fetch              { }
+ sub search             { }
+ sub iterator           { }
+ sub count              { }
+ sub search_related     { }
+ sub iterator_related   { }
+ sub count_related      { }
  
  1;
  
@@ -136,22 +139,38 @@
 
 =over
 
-=item fetch
+=item fetch( I<args> )
 
-Returns CatalystX::CRUD::Object->new()->read()
+Should return the equivalent of 
+CatalystX::CRUD::Object->new( I<args> )->read().
 
-=item search
+=item search( I<query> )
 
 Returns zero or more CXCO instances as an array or arrayref.
+I<query> may be the return value of make_query().
 
-=item iterator
+=item iterator( I<query> )
 
-Like search() but returns an iterator conforming to the CatalystX::CRUD::Iterator API.
+Like search() but returns an iterator conforming to the 
+CatalystX::CRUD::Iterator API.
 
-=item count
+=item count( I<query> )
 
 Like search() but returns an integer.
 
+=item search_related( I<obj>, I<relationship> )
+
+Returns zero or more CXCO instances like search().
+The instances are related to I<obj> via I<relationship>.
+
+=item iterator_related( I<obj>, I<relationship> )
+
+Like search_related() but returns an iterator.
+
+=item count_related( I<obj>, I<relationship> )
+
+Like search_related() but returns an integer.
+
 =back
 
 =cut
@@ -166,10 +185,13 @@
     }
 }
 
-sub fetch    { shift->throw_error("must implement fetch") }
-sub search   { shift->throw_error("must implement search") }
-sub iterator { shift->throw_error("must implement iterator") }
-sub count    { shift->throw_error("must implement count") }
+sub fetch            { shift->throw_error("must implement fetch") }
+sub search           { shift->throw_error("must implement search") }
+sub iterator         { shift->throw_error("must implement iterator") }
+sub count            { shift->throw_error("must implement count") }
+sub search_related   { shift->throw_error("must implement search_related") }
+sub iterator_related { shift->throw_error("must implement iterator_related") }
+sub count_related    { shift->throw_error("must implement count_related") }
 
 =head1 OPTIONAL METHODS
 
@@ -221,11 +243,27 @@
                                           # $c->model('Foo')->make_query()
 
 
+=item add_related( I<obj>, I<rel_name>, I<foreign_value> )
+
+Associate foreign object identified by I<foreign_value> with I<obj>
+via the relationship I<rel_name>.
+
+It is up to the subclass to implement this method.
+
+=item rm_related( I<obj>, I<rel_name>, I<foreign_value> )
+
+Dissociate foreign object identified by I<foreign_value> from I<obj>
+via the relationship I<rel_name>.
+
+It is up to the subclass to implement this method.
+
 =back
 
 =cut
 
-sub make_query { shift->throw_error("must implement make_query()") }
+sub make_query  { shift->throw_error("must implement make_query()") }
+sub add_related { shift->throw_error("must implement add_related()") }
+sub rm_related  { shift->throw_error("must implement rm_related()") }
 
 1;
 

Modified: CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/ModelAdapter.pm
===================================================================
--- CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/ModelAdapter.pm	2008-08-20 21:50:36 UTC (rev 8236)
+++ CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/ModelAdapter.pm	2008-08-21 05:52:10 UTC (rev 8237)
@@ -26,6 +26,9 @@
  sub iterator   { }
  sub count      { }
  sub make_query { }
+ sub search_related     { }
+ sub iterator_related   { }
+ sub count_related      { }
  
  1;
  
@@ -109,7 +112,7 @@
 
 sub count { shift->throw_error("must implement count") }
 
-=head2 make_query( I<context>, I<controller> )
+=head2 make_query( I<controller>, I<context> )
 
 Should return appropriate values for passing to search(), iterator() and
 count(). See CataystX::CRUD::Model for examples.
@@ -118,6 +121,44 @@
 
 sub make_query { shift->throw_error("must implement make_query()") }
 
+=head2 search_related( I<controller>, I<context>, I<obj>, I<relationship> )
+
+Returns zero or more CXCO instances like search().
+The instances are related to I<obj> via I<relationship>.
+
+=head2 iterator_related( I<controller>, I<context>, I<obj>, I<relationship> )
+
+Like search_related() but returns an iterator.
+
+=head2 count_related( I<controller>, I<context>, I<obj>, I<relationship> )
+
+Like search_related() but returns an integer.
+
+=cut
+
+sub search_related   { shift->throw_error("must implement search_related") }
+sub iterator_related { shift->throw_error("must implement iterator_related") }
+sub count_related    { shift->throw_error("must implement count_related") }
+
+=head2 add_related( I<controller>, I<context>, I<obj>, I<rel_name>, I<foreign_value> )
+
+Associate foreign object identified by I<foreign_value> with I<obj>
+via the relationship I<rel_name>.
+
+It is up to the subclass to implement this method.
+
+=head2 rm_related( I<controller>, I<context>, I<obj>, I<rel_name>, I<foreign_value> )
+
+Dissociate foreign object identified by I<foreign_value> from I<obj>
+via the relationship I<rel_name>.
+
+It is up to the subclass to implement this method.
+
+=cut
+
+sub add_related { shift->throw_error("must implement add_related()") }
+sub rm_related  { shift->throw_error("must implement rm_related()") }
+
 =head1 CRUD Methods
 
 The following methods are implemented in CatalystX::CRUD::Object when

Modified: CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD.pm
===================================================================
--- CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD.pm	2008-08-20 21:50:36 UTC (rev 8236)
+++ CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD.pm	2008-08-21 05:52:10 UTC (rev 8237)
@@ -2,7 +2,7 @@
 
 use warnings;
 use strict;
-use Catalyst::Exception;
+use Carp;
 
 our $VERSION = '0.29_01';
 
@@ -44,7 +44,8 @@
 
 =head2 throw_error( I<msg> )
 
-Throws Catalyst::Exception. Override to manage errors in some other way.
+Throws exception using Carp::croak (confess() if CATALYST_DEBUG env var
+is set). Override to manage errors in some other way.
 
 NOTE that if in your subclass throw_error() is not fatal and instead
 returns a false a value, methods that call it will, be default, continue
@@ -55,7 +56,7 @@
 sub throw_error {
     my $self = shift;
     my $msg = shift || 'unknown error';
-    Carp::confess($msg);
+    $ENV{CATALYST_DEBUG} ? Carp::confess($msg) : Carp::croak($msg);
 }
 
 =head1 AUTHOR




More information about the Catalyst-commits mailing list