NAME

Dancer::Plugin::Resource - A plugin for writing declarative RESTful apps with Dancer

VERSION

version 1.131120

SYNOPSIS

package MyWebService;

use Dancer;
use Dancer::Plugin::Resource;

prepare_serializer_for_format;

resource 'users';

# generates '/users/:user_id' and '/users/:user_id.:format'
sub user_GET {
    User->find(params->{user_id});
    ...
}

# curl http://mywebservice/user/42.json
{ "id": 42, "name": "John Foo", email: "john.foo@example.com"}

# curl http://mywebservice/user/42.yml
--
id: 42
name: "John Foo"
email: "john.foo@example.com"

DESCRIPTION

Dancer::Plugin::Resource is a dancer plugin aimed at simplifying and aiding in writing RESTful web services and applications in Dancer. It borrows ideas from both Ruby on Rails and Catalyst::Action::REST, while adding some new ones to boot. At its core it is used to combine two things:

  1. generate routes automatically for a 'resource' and map them to easily named functions.

  2. handle automatic serialization based off of what the user requests.

KEYWORDS

resource

This keyword is the meat of Dancer::Plugin::Resource. It lets you declare a resource your application will handle.

By default, you can pass in a mapping of CRUD actions to subrefs that will align to auto-generated routes: At its simplest, you can call it with no arguments. This will create the following routes, and try to map them to functions in the namespace you called it from.

resource 'users';

# this defines the following routes:

# POST /user
# POST /user.:format
sub user_POST { ... }

# GET /user/:id
# GET /user/:id.:format
sub user_GET { ... }

# PUT /user/:id
# PUT /user/:id.:format
sub user_PUT { ... }

# DELETE /user/:id
# DELETE /user/:id.:format
sub user_DELETE { ... }

# GET /user
# GET /user.:format
sub user_INDEX { ... }

The optional :format param is used by the prepare_serializer_for_format 'after' hook, which is described in more detail below. In short, it allows '.xml' or '.json' suffixes to control the format of data returned by the route.

An example of more complicated usage:

use Dancer::Plugin::Resource;

resource 'users',
    member => [qw/posts/],
    collection => [qw/log/],
    load => sub { schema->User->find(param 'user_id'); },
    load_all => sub { schema->User->all; };

resource 'accounts',
    parent => 'user',
    params => [qw/composite key/];

# HTTP $resource_VERB is mapped automatically for actions on the resource

# GET /users
sub users_INDEX {
    my ($users) = @_;   # returnval of load_all is passed in
}

# HTTP $VERB_$SINGULAR is mapped automatically for actions on elements of the resource

# POST /users
sub user_POST {
    # ...
}

# GET /users/:user_id
sub user_GET {
    my ($user) = @_;    # returnval of load is passed in
    # ...
}

# param id is inflected from the plural resource
# PUT /users/:user_id
sub user_PUT { my ($user) = @_; }

# DELETE /users/:user_id
sub user_DELETE { my ($user) = @_; }

# The member collection is attached to the members of the resource
# All CRUD verbs are automatically mapped
# GET /users/:user_id/posts
sub user_posts_GET { }

# likewise for collection methods
# POST /users/logs
sub users_logs_POST { }

# The accounts resource nests underneath user with the parent keyword
# the params keyword overrides the default params set by the route
# POST /users/:user_id/accounts
sub account_CREATE { }

# GET /users/:user_id/accounts/:composite/:key
sub account_GET { }

Mapping CRUD methods to routes is done automatically by inspecting the symbol table.

A full list of keywords that can be passed to resource is listed below. All are optional.

params

Defines the list of params that the given resource takes in its part of the path. Takes scalar or arrayref for 1 or multiple params.

resource 'users', params => [qw/foo bar/]; # /users/:foo/:bar

load/load_all

Takes a coderef. Methods called on element of the resource (read/update/delete) will receive load returnval in @_. Methods on the resource itself (index) will receive load_all in @_. Create does not receive any arguments. An alternative to @_ would be to use Dancers's 'vars' functionality for scope outside of the given route.

member

Declares additional methods attached to the given resource. Takes either a scalar or an arrayref.

resource 'users', member => 'posts';
sub read_users_posts { } # GET /users/:user_id/posts

collection

Like member methods, but attached to the root resource, and not the instance.

resource 'users', collection => [qw/posts/];
sub create_users_posts { } # POST /users/posts

parent

Each time a resource is declared its prefix and route is stored internally. If you declare a resource as a child of an already defined resource, the parents resource will be set as a prefix automatically, and the old prefix will be restored when done.

resource 'users';
resource 'posts', parent => 'users';
resource 'comments', parent => 'posts';

# /users/:user_id
# /users/:user_id/posts/:post_id
# /users/:user_id/posts/:post_id/comments/:comment_id

helpers

Some helpers are available. This helper will set an appropriate HTTP status for you.

status_ok

status_ok({users => {...}});

Set the HTTP status to 200

status_created

status_created({users => {...}});

Set the HTTP status to 201

status_accepted

status_accepted({users => {...}});

Set the HTTP status to 202

status_bad_request

status_bad_request("user foo can't be found");

Set the HTTP status to 400. This function as for argument a scalar that will be used under the key error.

status_not_found

status_not_found("users doesn't exists");

Set the HTTP status to 404. This function as for argument a scalar that will be used under the key error.

prepare_serializer_for_format

When this pragma is used, a before filter is set by the plugin to automatically change the serializer when a format is detected in the URI.

That means that each route you define with a :format token will trigger a serializer definition, if the format is known.

This lets you define all the REST actions you like as regular Dancer route handlers, without explicitly handling the outgoing data format.

LICENCE

This module is released under the same terms as Perl itself. This module is a fork of Dancer::Plugin::REST written by Alexis Sukrieh <sukria@sukria.net> and Franck Cuny.

SEE ALSO

Dancer Dancer::Plugin::REST http://en.wikipedia.org/wiki/Representational_State_Transfer

AUTHOR

Matthew Phillips <mattp@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2013 by Matthew Phillips.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

2 POD Errors

The following errors were encountered while parsing the POD:

Around line 484:

'=item' outside of any '=over'

Around line 492:

You forgot a '=back' before '=head1'