[Catalyst-commits] r7713 - in
Catalyst-Controller-REST-DBIC-Item/trunk/0.01:
lib/Catalyst/Controller/REST/DBIC
lib/Catalyst/Helper/Controller/REST/DBIC t
jshirley at dev.catalyst.perl.org
jshirley at dev.catalyst.perl.org
Wed May 7 18:15:03 BST 2008
Author: jshirley
Date: 2008-05-07 18:15:02 +0100 (Wed, 07 May 2008)
New Revision: 7713
Modified:
Catalyst-Controller-REST-DBIC-Item/trunk/0.01/lib/Catalyst/Controller/REST/DBIC/Item.pm
Catalyst-Controller-REST-DBIC-Item/trunk/0.01/lib/Catalyst/Helper/Controller/REST/DBIC/Item.pm
Catalyst-Controller-REST-DBIC-Item/trunk/0.01/t/00-load.t
Log:
Better pod, renamed the rest base midpoints to have a rest_ prefix.
Modified: Catalyst-Controller-REST-DBIC-Item/trunk/0.01/lib/Catalyst/Controller/REST/DBIC/Item.pm
===================================================================
--- Catalyst-Controller-REST-DBIC-Item/trunk/0.01/lib/Catalyst/Controller/REST/DBIC/Item.pm 2008-05-07 15:19:27 UTC (rev 7712)
+++ Catalyst-Controller-REST-DBIC-Item/trunk/0.01/lib/Catalyst/Controller/REST/DBIC/Item.pm 2008-05-07 17:15:02 UTC (rev 7713)
@@ -9,7 +9,7 @@
=head1 NAME
-Catalyst::Controller::REST::DBIC::Item - Common base class for typical REST
+Catalyst::Controller::REST::DBIC::Item - (EXPERIMENTAL) Common base class for typical REST
actions against a DBIx::Class object
=head1 VERSION
@@ -18,12 +18,13 @@
=cut
-our $VERSION = '0.01';
+our $VERSION = '0.01001';
=head1 DESCRIPTION
-This is a controller base class that is designed to build some conventions
-around integrating REST and DBIC together in a Catalyst application.
+This is an experimental controller base class that is designed to build some
+conventions around integrating REST and DBIC together in a Catalyst
+application.
The idea of this class is that, in the simplest terms, each item in a REST
application has one URL to interface with it. Typically, these objects have a
@@ -31,6 +32,18 @@
the repetition in your REST classes and allow you to focus on just handling
the individual verbs (GET, PUT, POST, etc)
+=head1 PHILOSOPHY
+
+The general ideas for this module are such that I don't expect it to be of the
+most use for a CRUD application designed to function in a browser. Most
+modern browsers support all the REST verbs via XmlHttpRequest but standard
+requests are still limited to GET and POST. This package will have the most
+influence in a webservice scenario, and I hope that adapter classes can be
+built upon this one that will combine L<Catalyst::Request::REST::ForBrowsers>
+and other utilities to create controllers that work equally well in a
+browser-based setting.
+
+
=head1 SYNOPSIS
package MyApp::Controller::Person;
@@ -42,19 +55,53 @@
'default' => 'text/html'
# And, our bindings to DBIC, will use
# $c->model('Schema::Person') effectively.
- resultset => 'Schema:;Person',
- # Optional configuration for templates
- templates => {
- not_found => 'errors/not_found.tt'
- }
+ class => 'Schema::Person',
+ # To find a record, $c->model($class)->search( $item_key => $key )
+ item_key => 'name',
+ # If you want to call a method before sending it to the serializers
+ serialize_method => 'serialize',
+ # Set to 0 if you don't want to call the above serialize method
+ # if the request is in a browser
+ browser_serialize => 0
);
# This operates off of chained, and requires rest_base to be defined
-
sub rest_base : Chained('.') PathPart('person') CaptureArgs(0) { }
- 1;
+=head1 Overriding Default Methods
+Catalyst::Controller::REST::DBIC::Item operates by using Chained, which allows
+for midpoints to be overridden easily as long as you maintain the conventions.
+
+If you want to override one of the default chained midpoints, you only have
+to be mindful of which stash key to set. By default, the stash key:
+C<< $c->stash->{rest}->{item} >> is used for fetching a single item. If you
+want to add additional DBIC logic, such as a prefetch, you can override
+the item_base midpoint and properly set the stash. Here is an example from
+the L<http://www.iwatchsoccer.com> source (available at
+L<http://our.coldhardcode.com/svn/IWS>, which prefetches games to reduce the
+total number of queries.
+
+ sub item_base : Chained('rest_base') PathPart('') CaptureArgs(1) {
+ my ( $self, $c, $identifier ) = @_;
+
+ # just populate $c->stash->{rest}->{item} and item_GET, etc
+ $c->stash->{rest}->{item} = $self->get_item($c, $identifier)->search(
+ {
+ 'games.end_time' => { '>=', $c->stash->{now} }
+ },
+ {
+ prefetch => {
+ games => [
+ 'home', 'visitor',
+ { broadcasts => 'network' }
+ ]
+ }
+ }
+ )->single;
+ }
+
+
=head1 CONFIGURATION
=over
@@ -89,11 +136,23 @@
=cut
-sub list : Chained('rest_base') PathPart('') Args(0) ActionClass('REST') {
+sub rest_list : Chained('rest_base') PathPart('') Args(0) ActionClass('REST') {
}
-sub list_GET {
+=head2 rest_list_GET
+
+The simple method that handles GET actions on the list action (A call to
+C</foo>).
+
+This method will call the C<serialize_method>, if configured, as well as respect
+the C<browser_serialize> configuration setting if the request looks like it
+is coming from a browser (which requires L<Catalyst::Request::REST::ForBrowsers>
+to be loaded).
+
+=cut
+
+sub rest_list_GET {
my ( $self, $c ) = @_;
my $rs = $self->get_rs($c);
@@ -114,24 +173,54 @@
}
-=head2 rest_item PathPart('') CaptureArgs(1)
+=head2 rest_item_base : Chained('rest_base') PathPart('') CaptureArgs(1)
-This method is used to handle triggering the single item methods. Override
-rest_item_GET, rest_item_POST, etc to have custom behavior.
+This chain midpoint fetches the record by the captured argument (which should
+be the record identifier).
+Override this method if you want to customize how the record is fetched. It
+is expected that if a record is found, C<< $c->stash->{rest}->{item} >> is set.
+If not, the default GET request will return not found.
+
=cut
-sub item_base : Chained('rest_base') PathPart('') CaptureArgs(1) {
+sub rest_item_base : Chained('rest_base') PathPart('') CaptureArgs(1) {
my ( $self, $c, $pk1 ) = @_;
- $c->stash->{rest}->{item} = $self->get_item( $c, $pk1 )->first;
+ $c->stash->{rest}->{item} = $self->get_item( $c, $pk1 )->single;
}
-sub item : Chained('item_base') PathPart('') Args(0) ActionClass('REST') {
+=head2 rest_item
+
+This method chains to rest_item_base, has 0 arguments and uses
+L<Catalyst::Action::REST>.
+
+This method is used to handle triggering the single item methods. Override
+rest_item_GET, rest_item_POST, etc to have custom serialization behavior.
+
+If you want to override the item selection, override rest_item_base
+
+=cut
+
+sub rest_item : Chained('rest_item_base') PathPart('') Args(0) ActionClass('REST') {
my ( $self, $c ) = @_;
}
-sub item_GET {
+=head2 rest_item_GET
+
+The default method for handling a simple GET request. This will serialize
+however L<Catalyst::Controller::REST> is configured for the controller, and
+will call the C<serialize_method> if configured (while respecting the
+C<browser_serialize> configuration setting).
+
+If the item is not found (which means C<< $c->stash->{rest}->{item} >> is not
+defined) it will return a status_not_found result, with the message:
+
+ message => $c->localize('ITEM_NOT_FOUND') );
+
+=cut
+
+sub rest_item_GET {
my ( $self, $c ) = @_;
my $item;
unless ( $item = $c->stash->{rest}->{item} ) {
@@ -156,8 +245,13 @@
return $self->status_ok( $c, entity => $entity );
}
-=head1 get_item($c, $identifier)
+=head1 HELPER METHODS
+The following methods are convenience methods that can be used in your methods
+to fetch items out of DBIC.
+
+=head2 get_item($context, $identifier)
+
This method should return a result set that points to a single item that is
identified by $identifier.
@@ -183,8 +277,22 @@
}
}
+=head2 get_rs($context)
+
+This fetches the result set to be used. This is a good point to override for
+adding things like pagination. A simple example for overriding would be:
+
+ sub get_rs {
+ my $rs = shift->next::method(@_);
+ return $rs->search(undef, { rows => 10, page => 1 });
+ }
+
+Just make sure this always returns a result set.
+
+=cut
+
sub get_rs {
- my ( $self, $c, $item ) = @_;
+ my ( $self, $c ) = @_;
my $model = $self->{class};
my $rs = $c->model($model);
croak "Unable to find DBIC resultset $model, check config"
Modified: Catalyst-Controller-REST-DBIC-Item/trunk/0.01/lib/Catalyst/Helper/Controller/REST/DBIC/Item.pm
===================================================================
--- Catalyst-Controller-REST-DBIC-Item/trunk/0.01/lib/Catalyst/Helper/Controller/REST/DBIC/Item.pm 2008-05-07 15:19:27 UTC (rev 7712)
+++ Catalyst-Controller-REST-DBIC-Item/trunk/0.01/lib/Catalyst/Helper/Controller/REST/DBIC/Item.pm 2008-05-07 17:15:02 UTC (rev 7713)
@@ -14,10 +14,28 @@
=head1 DESCRIPTION
-Helper to create REST Base classes.
+Helper to create REST Base classes. After this, you should be reading up on
+L<Catalyst::Controller::REST::DBIC::Item>
+=head1 METHODS
+
+=head2 mk_compclass
+
+This generates the individual REST classes
+
+=cut
+
+sub mk_compclass {
+ my ( $self, $helper, $schema_class ) = @_;
+ $helper->{schema_class} = $helper;
+ my $file = $helper->{file};
+ $helper->render_file( 'compclass', $file );
+}
+
=head1 SEE ALSO
+L<Catalyst::Controller::REST::DBIC::Item>
+
L<Catalyst::Action::REST>
L<Catalyst::Model::DBIC::Schema>
@@ -33,13 +51,8 @@
=cut
-sub mk_compclass {
- my ( $self, $helper, $schema_class ) = @_;
- $helper->{schema_class} = $helper;
- my $file = $helper->{file};
- $helper->render_file( 'compclass', $file );
-}
+
1;
__DATA__
Modified: Catalyst-Controller-REST-DBIC-Item/trunk/0.01/t/00-load.t
===================================================================
--- Catalyst-Controller-REST-DBIC-Item/trunk/0.01/t/00-load.t 2008-05-07 15:19:27 UTC (rev 7712)
+++ Catalyst-Controller-REST-DBIC-Item/trunk/0.01/t/00-load.t 2008-05-07 17:15:02 UTC (rev 7713)
@@ -18,12 +18,12 @@
# Create a book called 'name'
my $res = $mech->get('/book/test_book', 'Content-type' => 'text/x-yaml' );
-diag( $res->content );
+
is($res->code, '404', "Book doesn't exist");
my $test_data = YAML::Syck::Dump({ name => "test_book", isbn => "1234" });
-diag( $test_data );
-my $res = $mech->post( '/book/test_book',
+
+$res = $mech->post( '/book/test_book',
'Content-type' => 'text/x-yaml',
Content => $test_data
);
@@ -31,7 +31,7 @@
is($res->code, '405', "Book has no post method");
like($res->content, qr/Method POST not implemented/, 'No post on book');
-my $res = $mech->put( '/book/test_book',
+$res = $mech->put( '/book/test_book',
'Content-type' => 'text/x-yaml',
Content => $test_data
);
More information about the Catalyst-commits
mailing list