File Coverage

blib/lib/OX/RouteBuilder/REST.pm
Criterion Covered Total %
statement 38 41 92.6
branch 5 8 62.5
condition n/a
subroutine 7 7 100.0
pod 0 2 0.0
total 50 58 86.2


line stmt bran cond sub pod time code
1             package OX::RouteBuilder::REST;
2              
3             # ABSTRACT: OX::RouteBuilder which routes to an action method in a controller class based on HTTP verbs
4             our $VERSION = '0.004'; # VERSION
5              
6 1     1   3402713 use Moose;
  1         10  
  1         6  
7 1     1   6403 use namespace::autoclean;
  1         2  
  1         13  
8 1     1   96 use Try::Tiny;
  1         2  
  1         682  
9              
10             with 'OX::RouteBuilder';
11              
12             sub import {
13 1     1   9 my $caller = caller;
14 1         4 my $meta = Moose::Util::find_meta($caller);
15 1         17 $meta->add_route_builder('OX::RouteBuilder::REST');
16             }
17              
18             sub compile_routes {
19 6     6 0 30 my $self = shift;
20 6         11 my ($app) = @_;
21              
22 6         173 my $spec = $self->route_spec;
23 6         174 my $params = $self->params;
24 6         50 my ( $defaults, $validations ) =
25             $self->extract_defaults_and_validations($params);
26 6         103 $defaults = { %$spec, %$defaults };
27              
28             my $target = sub {
29 4     4   186181 my ($req) = @_;
30              
31 4         22 my $match = $req->mapping;
32 4         151 my $c = $match->{controller};
33 4         10 my $a = $match->{action};
34              
35 4         8 my $err;
36 4         32 my $s = try { $app->fetch($c) } catch { ($err) = split "\n"; undef };
  4         194  
  0         0  
  0         0  
37             return [
38 4 50       8553 500, [], [ "Cannot resolve $c in " . blessed($app) . ": $err" ]
39             ]
40             unless $s;
41              
42 4         21 my $component = $s->get;
43 4         8730 my $method = uc( $req->method );
44 4         93 my $action = $a . '_' . $method;
45              
46 4 50       23 if ( $component->can($action) ) {
47 4         23 return $component->$action(@_);
48             }
49             else {
50 0         0 return [ 500, [],
51             ["Component $component has no method $action"] ];
52             }
53 6         37 };
54              
55             return {
56 6         153 path => $self->path,
57             defaults => $defaults,
58             target => $target,
59             validations => $validations,
60             };
61             }
62              
63             sub parse_action_spec {
64 4     4 0 139464 my $class = shift;
65 4         10 my ($action_spec) = @_;
66              
67 4 50       13 return if ref($action_spec);
68 4 100       21 return unless $action_spec =~ /^REST\.(\w+)\.(\w+)$/;
69              
70             return {
71 2         15 controller => $1,
72             action => $2,
73             name => $action_spec,
74             };
75             }
76              
77             __PACKAGE__->meta->make_immutable;
78              
79             1;
80              
81             __END__
82              
83             =pod
84              
85             =encoding UTF-8
86              
87             =head1 NAME
88              
89             OX::RouteBuilder::REST - OX::RouteBuilder which routes to an action method in a controller class based on HTTP verbs
90              
91             =head1 VERSION
92              
93             version 0.004
94              
95             =head1 SYNOPSIS
96              
97             package MyApp;
98             use OX;
99             use OX::RouteBuilder::REST;
100              
101             has thing => (
102             is => 'ro',
103             isa => 'MyApp::Controller::Thing',
104             );
105              
106             router as {
107             route '/thing' => 'REST.thing.root';
108             route '/thing/:id' => 'REST.thing.item';
109             };
110              
111              
112             package MyApp::Controller::Thing;
113             use Moose;
114              
115             sub root_GET {
116             my ($self, $req) = @_;
117             ... # return a list if things
118             }
119              
120             sub root_PUT {
121             my ($self, $req) = @_;
122             ... # create a new thing
123             }
124              
125             sub item_GET {
126             my ($self, $req, $id) = @_;
127             ... # view a thing
128             }
129              
130             sub item_POST {
131             my ($self, $req, $id) = @_;
132             ... # update a thing
133             }
134              
135             =head1 DESCRIPTION
136              
137             This is an L<OX::RouteBuilder> which routes to an action method in a
138             controller class based on HTTP verbs. It's a bit of a mixture between
139             L<OX::RouteBuilder::ControllerAction> and
140             L<OX::RouteBuilder::HTTPMethod>.
141              
142             To enable this RouteBuilder, you need to C<use OX::RouteBuilder::REST>
143             in your main application class.
144              
145             The C<action_spec> should be a string in the form
146             C<"REST.$controller.$action">, where C<$controller> is the name of a
147             service which provides a controller instance. For each HTTP verb you
148             want to support you will need to set up an action with the name
149             C<$action_$verb> (e.g. C<$action_GET>, C<$action_PUT>, etc). If no
150             matching action-verb-method is found, a 404 error will be returned.
151              
152             C<controller> and C<action> will also be automatically added as
153             defaults for the route, as well as C<name> (which will be set to
154             C<"REST.$controller.$action">).
155              
156             To generate a link to an action, use C<uri_for> with either the name
157             (eg C<"REST.$controller.$action">), or by passing a HashRef C<{
158             controller => $controller, action => $action }>. See F<t/test.t>
159             for some examples.
160              
161             =for Pod::Coverage import
162             compile_routes
163             parse_action_spec
164              
165             =head1 AUTHORS
166              
167             =over 4
168              
169             =item *
170              
171             Thomas Klausner <domm@plix.at>
172              
173             =item *
174              
175             Validad GmbH http://validad.com
176              
177             =back
178              
179             =head1 COPYRIGHT AND LICENSE
180              
181             This software is copyright (c) 2014 - 2021 by Thomas Klausner.
182              
183             This is free software; you can redistribute it and/or modify it under
184             the same terms as the Perl 5 programming language system itself.
185              
186             =cut