File Coverage

blib/lib/Dancer2/Controllers.pm
Criterion Covered Total %
statement 39 39 100.0
branch 10 12 83.3
condition 2 3 66.6
subroutine 8 8 100.0
pod 1 1 100.0
total 60 63 95.2


line stmt bran cond sub pod time code
1             package Dancer2::Controllers;
2              
3 4     4   709985 use strict;
  4         10  
  4         161  
4 4     4   26 use warnings;
  4         12  
  4         279  
5              
6 4     4   29 use Carp qw(croak);
  4         14  
  4         340  
7 4     4   24 use Exporter qw(import);
  4         7  
  4         165  
8 4     4   22 use MooseX::MethodAttributes;
  4         8  
  4         42  
9 4     4   64719 use Data::Dumper;
  4         23  
  4         3900  
10              
11             our $VERSION = '1.1';
12             our @EXPORT = qw(controllers);
13              
14             my %dsl;
15             @dsl{qw(get post put patch del any)} = qw(1 1 1 1 1 1);
16              
17             sub controllers {
18 8     8 1 1641067 my $classes = shift;
19              
20 8 100 66     110 croak
21             qq{Dancer2::Controllers::controllers expects a single, array-ref as it's argument, instead got $classes}
22             unless ref($classes) && ref($classes) eq 'ARRAY';
23              
24 7         26 my ($pkg) = caller;
25              
26 7         137 for (@$classes) {
27 7         17 my $class = $_;
28 7         162 my $meta = $class->meta;
29 5         320 my @methods = $meta->get_method_list;
30 5         6912 for (@methods) {
31 9         80268 my $method = $meta->get_method($_);
32 9 100       300 next unless $method->can('attributes');
33 6         11 for ( @{ $method->attributes } ) {
  6         544  
34 6         1706 my $method_name = $method->fully_qualified_name();
35              
36 6 100       80 if (/^Route$/x) {
37 1         15 croak
38             qq{Empty route declared, $method_name, did you mean to provide arguments?};
39             }
40              
41 5 50       25 next unless /^Route\(.*/x;
42 5         30 my ( $action, $location ) =
43             /^Route\((get|put|post|patch|del|any)\s=>\s'?"?([\w\/:_\-\[\]{}?]+)'?"?\)/x;
44              
45 5 100       35 croak
46             qq{Location is undefined for route attribute on method '$method_name'}
47             unless $location;
48             croak
49             qq{Invalid action $action for route attribute on method '$method_name' should be get, put, post, patch, del, any}
50 3 50       14 unless exists $dsl{$action};
51              
52             $pkg->can($action)
53 3     3   52 ->( $location, sub { $class->can( $method->name() )->(@_) } );
  3         553449  
54             }
55             }
56             }
57             }
58              
59             1;
60              
61             =encoding utf8
62              
63             =head1 NAME
64              
65             Dancer2::Controllers
66              
67             =head1 SYNOPSIS
68              
69             Dancer2::Controllers is a Spring-Boot esq wrapper for defining Dancer2 routes, it allows you to define
70             routes inside of modules using method attributes.
71              
72             =head1 EXAMPLE
73              
74             package MyApp::Controller;
75              
76             use Moose;
77              
78             BEGIN { extends 'Dancer2::Controllers::Controller' }
79              
80             sub hello_world : Route(get => /) {
81             "Hello World!";
82             }
83              
84             1;
85              
86             package main;
87              
88             use Dancer2;
89             use Dancer2::Controllers;
90              
91             controllers( ['MyApp::Controller'] );
92              
93             dance;
94              
95             =head1 API
96              
97             =head2 controllers
98              
99             controllers( [
100             'MyApp::Controller::Foo',
101             'MyApp::Controller::Bar'
102             ] );
103              
104             A subroutine that takes a list of controller module names, and registers their routes methods, annotated by the C<Route> attribute.