Dancer-Plugin-Resource

 view release on metacpan or  search on metacpan

lib/Dancer/Plugin/Resource.pm  view on Meta::CPAN

my $content_types = {
    json => 'application/json',
    yml  => 'text/x-yaml',
    xml  => 'application/xml',
};

my %routes;

# thanks leont
sub _function_exists {
    no strict 'refs';
    my $funcname = shift;
    return \&{$funcname} if defined &{$funcname};
    return;
}

sub prepare_serializer_for_format {
    my $conf        = plugin_setting;
    my $serializers = (
        ($conf && exists $conf->{serializers})
        ? $conf->{serializers}
        : { 'json' => 'JSON',
            'yml'  => 'YAML',
            'xml'  => 'XML',
            'dump' => 'Dumper',
        }
    );

    hook 'before' => sub {
        my $format = params->{'format'};
        if (not defined $format) {
            set serializer => 'Mutable';
            return;
        }

        return unless defined $format;

        my $serializer = $serializers->{$format};
        unless (defined $serializer) {
            return halt(
                Dancer::Error->new(
                    code    => 404,
                    message => "unsupported format requested: " . $format
                )
            );
        }

        set serializer => $serializer;
        my $ct = $content_types->{$format} || setting('content_type');
        content_type $ct;
    };
}
register prepare_serializer_for_format => \&prepare_serializer_for_format;

register resource => sub {
    my ($resource, %options) = @_;

    my $params = ':id';
    my ($old_prefix, $parent_prefix);

    unless ($options{skip_prepare_serializer} || ((caller)[1] =~ /^(?:t|xt)/)) {
        prepare_serializer_for_format;
    }

    # if this resource is a nested child resource, manage the prefix
    $old_prefix = Dancer::App->current->prefix || '';
    $parent_prefix = '';

    if ($options{parent} and $routes{$options{parent}}) {
        prefix $parent_prefix = $routes{$options{parent}};
    }
    else {
        $parent_prefix = $old_prefix;
    }

    # create a default for the load funcs
    $options{$_} ||= sub { undef } for (qw/load load_all/);

    # if member => 'foo' is passed, turn it into an array
    for my $type (qw/member collection/) {
        if ($options{$type} && ref $options{$type} eq '') {
            $options{$type} = [$options{$type}];
        }
    }

    # by default take the singular resource as the param name (ie :user for users)
    my ($singular_resource, $plural_resource) = (Lingua::EN::Inflect::Number::to_S($resource), $resource);

    # or if the user wants to override to take multiple params, ie /user/:foo/:bar/:baz
    # allow it. This could be useful for composite key schemas
    if ( my $p = $options{params} ) {
        $p = ref $p ? $p : [$p];
        $params = join '/', map ":${_}", @{$p};
    }
    else {
        $params = ":${singular_resource}_id";
    }

    my ($package) = caller;

    # main resource endpoints
    # CRUD
    _post(
        _endpoint(
            path     => $plural_resource,
            params   => '',
            verbs    => [qw/POST create/],
            function => $singular_resource
        )
    );

    _get(
        _endpoint(
            path     => $plural_resource,
            params   => $params,
            verbs    => [qw/GET get read/],
            loader   => $options{load},
            function => $singular_resource
        )
    );



( run in 0.710 second using v1.01-cache-2.11-cpan-63c85eba8c4 )