1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
You can thanks [[http://github.com/bobtfish][bobtfish]] for being such a
pedantic guy, 'cause now you will have a better chained examples. He
forked my repository from GitHub and fix some code that I'll explain
here.
*** lib/MyFeedReader.pm
#+BEGIN_SRC perl
package MyFeedReader;
+use Moose;
+use namespace::autoclean;
-use strict;
-use warnings;
-
-use Catalyst::Runtime '5.70';
+use Catalyst::Runtime '5.80';
-use parent qw/Catalyst/;
+extends 'Catalyst';
#+END_SRC
You can see that he use [[http://search.cpan.org/perldoc?Moose][Moose]],
so we can remove
#+BEGIN_SRC perl
use strict;
use warnings;
#+END_SRC
and have a more elegant way to inherit from
[[http://search.cpan.org/perldoc?Catalyst][Catalyst]] with
#+BEGIN_SRC perl
extends 'Catalyst';
#+END_SRC
instead of
#+BEGIN_SRC perl
use parent qw/Catalyst/;
#+END_SRC
He also have updated the *Catalyst::Runtime* version, and added
*namespace::autoclean*. The purpose of this module is to keep imported
methods out of you namespace. Take a look at the
"documentation":http://search.cpan.org/perldoc?namespace::autoclean,
it's easy to understand how and why it's usefull.
*** lib/MyFeedReader/Controller/Root.pm
#+BEGIN_SRC perl
-use strict;
-use warnings;
-use parent 'Catalyst::Controller';
+use Moose;
+use namespace::autoclean;
+BEGIN { extends 'Catalyst::Controller' }
-sub index :Path :Args(0) {
+sub root : Chained('/') PathPart() CaptureArgs(0) {}
+
+sub index : Chained('root') PathPart('') Args(0) {
my ( $self, $c ) = @_;
# Hello World
$c->response->body( $c->welcome_message );
}
-sub default :Path {
+sub default : Private {
my ( $self, $c ) = @_;
$c->response->body( 'Page not found' );
$c->response->status(404);
#+END_SRC
A new method, =root=, that will be the root path for our application.
All our methods will be chained from this action. If start you catalyst
server and go to *http://localhost:3000/* you will be served with the
Catalyst's welcome message as before.
*** lib/MyFeedReader/Controller/Entry.pm
#+BEGIN_SRC perl
-use warnings;
+use Moose;
use MyAggregator::Entry;
-use parent 'Catalyst::Controller';
-
-__PACKAGE__->config->{namespace} = 'entry';
+use namespace::autoclean;
+BEGIN { extends 'Catalyst::Controller'; }
-sub view : Chained('/') : PathPart('entry') : Args(1) {
+sub view : Chained('/root') : PathPart('entry') : Args(1) {
my ( $self, $c, $id ) = @_;
$c->stash->{entry} = $c->model('KiokuDB')->lookup($id);
}
-1;
-
+__PACKAGE__->meta->make_immutable;
#+END_SRC
We extends the *Catalyst::Controller* in a Moose way, and the
=make_immutable= instruction is a Moose recommanded best practice (you
can alsa add =no Moose= after the make\_immutable).
*** lib/MyFeedreader/Controller/Feed.pm
#+BEGIN_SRC perl
+use Moose;
+use namespace::autoclean;
+BEGIN { extends 'Catalyst::Controller' }
-use strict;
-use warnings;
-use parent 'Catalyst::Controller';
+sub feed : Chained('/root') PathPart('feed') CaptureArgs(0) {}
-__PACKAGE__->config->{namespace} = 'feed';
-
-sub index : Path : Args(0) {
+sub index : Chained('feed') PathPart('') Args(0) {
my ( $self, $c ) = @_;
$c->stash->{feeds}
= [ $c->model('MyModel')->resultset('Feed')->search() ];
}
-sub view : Chained('/') : PathPart('feed/view') : Args(1) {
+sub view : Chained('feed') : PathPart('view') : Args(1) {
my ( $self, $c, $id ) = @_;
$c->stash->{feed}
= $c->model('MyModel')->resultset('Feed')->find($id);
}
-1;
+__PACKAGE__->meta->make_immutable;
#+END_SRC
We got =feed= which is chained to root. =index= is chained to feed, and
take no arguments. This method display the list of our feeds. And we got
the =view= method, chained to feed too, but with one argument, that
display the content of an entry.
If you start the application, you will see the following routes:
#+BEGIN_EXAMPLE
.-------------------------------------+--------------------------------------.
| Path Spec | Private |
+-------------------------------------+--------------------------------------+
| /root/entry/* | /root (0) |
| | => /entry/view |
| /root/feed | /root (0) |
| | -> /feed/feed (0) |
| | => /feed/index |
| /root/feed/view/* | /root (0) |
| | -> /feed/feed (0) |
| | => /feed/view |
| /root | /root (0) |
| | => /index |
'-------------------------------------+--------------------------------------'
#+END_EXAMPLE
I hope you got a better idea about chained action in catalyst now. And
again, thanks to bobtfish for the code.
|