[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