File Coverage

blib/lib/Catalyst/Plugin/URI.pm
Criterion Covered Total %
statement 13 15 86.6
branch 5 10 50.0
condition 3 5 60.0
subroutine 3 3 100.0
pod n/a
total 24 33 72.7


line stmt bran cond sub pod time code
1             package Catalyst::Plugin::URI;
2              
3 1     1   4469 use Moo::Role;
  1         20572  
  1         5  
4 1     1   3922 use Scalar::Util ();
  1         2  
  1         270  
5              
6             requires 'uri_for';
7              
8             our $VERSION = '0.002';
9              
10             sub uri {
11 5     5   522142 my ($c, $path, @args) = @_;
12              
13             # already is an $action
14 5 50 33     30 if(Scalar::Util::blessed($path) && $path->isa('Catalyst::Action')) {
15 0         0 return $c->uri_for($path, @args);
16             }
17              
18             # Hard error if the spec looks wrong...
19 5 50       23 die "$path is not a string" unless ref \$path eq 'SCALAR';
20 5 50       30 die "$path is not a controller.action specification" unless $path=~m/^(.*)\.(.+)$/;
21              
22 5 50 100     47 die "$1 is not a controller"
23             unless my $controller = $c->controller($1||'');
24              
25 5 50       372 die "$2 is not an action for controller ${\$controller->component_name}"
  0         0  
26             unless my $action = $controller->action_for($2);
27              
28 5         1154 return $c->uri_for($action, @args);
29             }
30              
31              
32             1;
33              
34             =head1 NAME
35              
36             Catalyst::Plugin::URI - Yet another sugar plugin for $c->uri_for
37              
38             =head1 SYNOPSIS
39              
40             Use the plugin in your application class:
41              
42             package MyApp;
43             use Catalyst 'URI';
44              
45             MyApp->setup;
46              
47             Then you can use it in your controllers:
48              
49             package MyApp::Controller::Example;
50              
51             use base 'Catalyst::Controller';
52              
53             sub make_a_url :Local {
54             my ($self, $c) = @_;
55             my $url = $c->uri("$controller.$action", \@args, \%query, \$fragment);
56             }
57              
58             This is just a shortcut with stronger error messages for:
59              
60             sub make_a_url :Local {
61             my ($self, $c) = @_;
62             my $url = $c->url_for(
63             $c->controller($controller)->action_for($action),
64             \@args, \%query, \$fragment);
65             }
66              
67             =head1 DESCRIPTION
68              
69             Currently if you want to create a URL to a controller's action properly the formal
70             syntax is rather verbose:
71              
72             my $url = $c->uri(
73             $c->controller($controller)->action_for($action),
74             \@args, \%query, \$fragment);
75              
76              
77             Which is verbose enough that i probably encourages people to do the wrong thing
78             and use a hard coded link path. This might later bite you if you need to change
79             your controllers and URL hierarchy.
80              
81             Also, this can lead to weird error messages that don't make if clear that your
82             $controller and $action are actually wrong. This plugin is an attempt to both
83             make the proper formal syntax a bit more tidy and to deliver harder error messages
84             if you get the names wrong.
85              
86             =head1 METHODS
87              
88             This plugin adds the following methods to your context
89              
90             =head2 uri
91              
92             Example:
93              
94             $c->uri("$controller.$action", \@parts, \%query, \$fragment);
95              
96             This is a sugar method which works the same as:
97              
98             my $url = $c->uri_for(
99             $c->controller($controller)->action_for($action),
100             \@args, \%query, \$fragment);
101              
102             Just a bit shorter, and also we check to make sure the $controller and
103             $action actually exist (and raise a hard fail if they don't with an error
104             message that is I think more clear than the longer version.
105              
106             You can also use a 'relative' specification for the action, which assumes
107             the current controller. For example:
108              
109             $c->uri(".$action", \@parts, \%query, \$fragment);
110              
111             Basically the same as:
112              
113             my $url = $c->uri_for(
114             $self->action_for($action),
115             \@args, \%query, \$fragment);
116              
117             Lastly For ease of use if the first argument is an action object we just pass it
118             down to 'uri_for'. That way you should be able to use this method for all types
119             of URL creation.
120              
121             =head1 OTHER SIMILAR OPTIONS
122              
123             L<Catalyst> offers a second way to make URLs that use the action private
124             name, the 'uri_for_action' method. However this suffers from a bug where
125             'path/action' and '/path/action' work the same (no support for relative
126             actions). Also this doesn't give you a very good error message if the action
127             private path does not exist, leading to difficult debugging issues sometimes.
128             Lastly I just personally prefer to look up an action via $controller->action_for(...)
129             over the private path, which is somewhat dependent on controller namespace
130             information that you might change.
131              
132             Prior art on CPAN doesn't seem to solve issues that I think actually exist (
133             for example older versions of L<Catalyst> required that you specify capture
134             args from args in a Chained action, there's plugins to address that but that
135             was fixed in core L<Catalyst> quite a while ago.) This plugin exists merely as
136             sugar over the formal syntax and tries to do nothing else fancy.
137              
138             =head1 AUTHOR
139              
140             John Napiorkowski L<email:jjnapiork@cpan.org>
141            
142             =head1 SEE ALSO
143            
144             L<Catalyst>
145              
146             =head1 COPYRIGHT & LICENSE
147            
148             Copyright 2015, John Napiorkowski L<email:jjnapiork@cpan.org>
149            
150             This library is free software; you can redistribute it and/or modify it under
151             the same terms as Perl itself.
152            
153             =cut