[Catalyst] Catalyst::Action::REST

Adam Jacob adam at stalecoffee.org
Mon Nov 20 19:48:58 GMT 2006


On Mon, Nov 20, 2006 at 10:48:54AM -0800, Bill Moseley wrote:
> So what does that look like in real life?  What if process_form() fails
> validation?
> 
> My urls look like this:
> 
>     /user           - list users
>     /user/edit/1234 - edit/update that specific user.
>     /user/edit      - create user
>     /user/delete/1233
> 
> My create, edit, and update all use the same interface (form) so seems
> to make sense that all those actions should use the same controller.
> It also means my template can be set automatically based on the
> controller's action name.

For the sake of argument, lets say you want to expose this as a REST
service.  We have a few things to define:

1) A "user" is a resource, and they are accessable through an URL.
2) Actions on a resource are determined by the HTTP Method I ask for.
3) Most operations can be seen as a transform of the data from another.
   For example, updating a User can usually be done by just changing the
   data structure returned from "GET"-ing the user.

A Sample controller would look like this (this is off the top of my
head, so it may or may not work):

## Code begins ##
package Foo::Controller::User;
use base 'Catalyst::Controller::REST';

sub user_list :Index :ActionClass('REST') { }

sub user_list_GET {
    my ($self, $c) = @_;
    
    my @users = $c->model('User')->list; # Made this up

    # Returns a 200 OK with the Serialized Array
    $self->status_ok($c, entity => \@users);
}

sub single_user :PathPart('user') :Chained :Args(1) :ActionClass('REST')
{}

sub single_user_GET {
    my ($self, $c, $user_id) = @_;

    my $user = $c->model('User')->find($user_id);
    if (defined($user)) {
        $self->status_ok($c, entity => $user);
    } else {
        $self->status_not_found($c, message => "I could not find User $user_id");
    }
}

sub single_user_PUT {
    my ($self, $c, $user_id) = @_;

    # The deserialized request is in $c->req->data
    my $user = $c->model('User')->create($user_id, $c->req->data);
    if (defined($user)) {
        $self->status_ok($c, entity => $user);
    } else {
        $self->status_bad_request($c, message => "Could not create $user_id");
    }
}

sub single_user_POST {
    my ($self, $c, $user_id) = @_;

    # The deserialized request is in $c->req->data
    my $user = $c->model('User')->update($user_id, $c->req->data);
    if (defined($user)) {
        $self->status_ok($c, entity => $user);
    } else {
        $self->status_bad_request($c, message => "Could not update $user_id");
    }
}

sub single_user_DELETE {
    my ($self, $c, $user_id) = @_;

    # The deserialized request is in $c->req->data
    my $user = $c->model('User')->delete($user_id);
    if (defined($user)) {
        $self->status_ok($c, entity => $user);
    } else {
        $self->status_bad_request($c, message => "Could not delete $user_id");
    }
}
## Code ends ##

That's the gist.  It's not the sort of thing you would use to power your
user-facing website; it's for building machine-useable web services.

Adam



More information about the Catalyst mailing list