File Coverage

blib/lib/Path/Dispatcher/Rule.pm
Criterion Covered Total %
statement 40 41 97.5
branch 12 12 100.0
condition n/a
subroutine 11 12 91.6
pod 3 5 60.0
total 66 70 94.2


line stmt bran cond sub pod time code
1             package Path::Dispatcher::Rule;
2             # ABSTRACT: predicate and codeblock
3              
4             our $VERSION = '1.08';
5              
6 32     32   27988 use Moo;
  32         64  
  32         174  
7 32     32   24487 use MooX::TypeTiny;
  32         9241  
  32         234  
8 32     32   409645 use Types::Standard qw(Bool);
  32         3066169  
  32         450  
9 32     32   42428 use Path::Dispatcher::Match;
  32         128  
  32         1615  
10              
11 32     32   266 use constant match_class => "Path::Dispatcher::Match";
  32         69  
  32         15879  
12              
13             has payload => (
14             is => 'ro',
15             predicate => 'has_payload',
16             );
17              
18             has prefix => (
19             is => 'ro',
20             isa => Bool,
21             default => 0,
22             );
23              
24             # support for deprecated "block" attribute
25 1     1 1 8 sub block { shift->payload(@_) }
26 1     1 0 273 sub has_block { shift->has_payload(@_) }
27             around BUILDARGS => sub {
28             my $orig = shift;
29             my $self = shift;
30              
31             my $args = $self->$orig(@_);
32             $args->{payload} ||= delete $args->{block}
33             if exists $args->{block};
34              
35             return $args;
36             };
37              
38             sub match {
39 381     381 1 6554 my $self = shift;
40 381         566 my $path = shift;
41 381         702 my %args = @_;
42              
43 381         1266 my $result;
44              
45 381 100       1505 if ($self->prefix) {
46 42         148 $result = $self->_prefix_match($path);
47             }
48             else {
49 339         1099 $result = $self->_match($path);
50             }
51              
52 381 100       1136 return if !$result;
53              
54 241 100       828 if (ref($result) ne 'HASH') {
55 1         26 die "Results returned from _match must be a hashref";
56             }
57              
58             my $match = $self->match_class->new(
59             path => $path,
60             rule => $self,
61 240 100       887 %{ $args{extra_constructor_args} || {} },
  240         5469  
62             %$result,
63             );
64              
65 240         61753 return $match;
66             }
67              
68             sub complete {
69 0     0 0 0 return (); # no completions
70             }
71              
72             sub _prefix_match {
73 42     42   71 my $self = shift;
74 42         128 return $self->_match(@_);
75             }
76              
77             sub run {
78 71     71 1 1731 my $self = shift;
79              
80 71         276 my $payload = $self->payload;
81              
82 71 100       245 die "No codeblock to run" if !$payload;
83 69 100       320 die "Payload is not a coderef" if ref($payload) ne 'CODE';
84              
85 67         324 $self->payload->(@_);
86             }
87              
88             __PACKAGE__->meta->make_immutable;
89 32     32   281 no Moo;
  32         86  
  32         209  
90              
91             1;
92              
93             __END__
94              
95             =pod
96              
97             =encoding UTF-8
98              
99             =head1 NAME
100              
101             Path::Dispatcher::Rule - predicate and codeblock
102              
103             =head1 VERSION
104              
105             version 1.08
106              
107             =head1 SYNOPSIS
108              
109             my $rule = Path::Dispatcher::Rule::Regex->new(
110             regex => qr/^quit/,
111             block => sub { die "Program terminated by user.\n" },
112             );
113              
114             $rule->match("die"); # undef, because "die" !~ /^quit/
115              
116             my $match = $rule->match("quit"); # creates a Path::Dispatcher::Match
117              
118             $match->run; # exits the program
119              
120             =head1 DESCRIPTION
121              
122             A rule has a predicate and an optional codeblock. Rules can be matched (which
123             checks the predicate against the path) and they can be ran (which invokes the
124             codeblock).
125              
126             This class is not meant to be instantiated directly, because there is no
127             predicate matching function. Instead use one of the subclasses such as
128             L<Path::Dispatcher::Rule::Tokens>.
129              
130             =head1 ATTRIBUTES
131              
132             =head2 block
133              
134             An optional block of code to be run. Please use the C<run> method instead of
135             invoking this attribute directly.
136              
137             =head2 prefix
138              
139             A boolean indicating whether this rule can match a prefix of a path. If false,
140             then the predicate must match the entire path. One use-case is that you may
141             want a catch-all rule that matches anything beginning with the token C<ticket>.
142             The unmatched, latter part of the path will be available in the match object.
143              
144             =head1 METHODS
145              
146             =head2 match path -> match
147              
148             Takes a path and returns a L<Path::Dispatcher::Match> object if it matched the
149             predicate, otherwise C<undef>. The match object contains information about the
150             match, such as the results (e.g. for regex, a list of the captured variables),
151             the C<leftover> path if C<prefix> matching was used, etc.
152              
153             =head2 run
154              
155             Runs the rule's codeblock. If none is present, it throws an exception.
156              
157             =head1 SUPPORT
158              
159             Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Path-Dispatcher>
160             (or L<bug-Path-Dispatcher@rt.cpan.org|mailto:bug-Path-Dispatcher@rt.cpan.org>).
161              
162             =head1 AUTHOR
163              
164             Shawn M Moore, C<< <sartak at bestpractical.com> >>
165              
166             =head1 COPYRIGHT AND LICENSE
167              
168             This software is copyright (c) 2020 by Shawn M Moore.
169              
170             This is free software; you can redistribute it and/or modify it under
171             the same terms as the Perl 5 programming language system itself.
172              
173             =cut