do not include .git directory
[catagits/Reaction.git] / old / Manual / Example.pod
CommitLineData
1f9daa1e 1=head1 NAME
2
3Reaction::Manual::Example - Simple Reaction example
4
5=head1 DESCRIPTION
6
7This tutorial will guide you through the process of setting up and testing a
8very basic CRUD application based on the database from
9L<DBIx::Class::Manual::Example>.
10
11You need at least a fairly basic understanding of L<DBIx::Class::Schema> for
12this example to have value for you.
13
14=head2 Installation
15
16Install L<DBIx::Class> via CPAN.
17
18Install Reaction from http://code2.0beta.co.uk/reaction/svn via SVN or SVK.
19
20Set up the database as mentioned in L<DBIx::Class::Manual::Example>. Don't do
21any of the DBIx::Class related stuff, only the SQLite database.
22
23=head2 Create the application
24
25 catalyst.pl Test::Reaction
26 cd Test-Reaction
27 script/test_reaction_create.pl Model Test::Reaction DBIC::Schema Test::Reaction::DB
28
29Also, remember to include Catalyst::Plugin::I18N in your plugin list, like
30this:
31
32 use Catalyst qw/-Debug ConfigLoader Static::Simple I18N/;
33
34=head2 Set up DBIx::Class::Schema
35
36In addition to the normal DBIC stuff, you need to moosify your DBIC classes.
37
38Change directory back from db to the directory app:
39
40 cd lib/Test/Reaction
41 mkdir DB
42
43Then, create the following DBIx::Class::Schema classes:
44
45DB.pm:
46
47 package Test::Reaction::DB;
48
49 use base 'DBIx::Class::Schema';
50
51 __PACKAGE__->load_classes;
52
53 1;
54
55DB/Artist.pm:
56
57 package Test::Reaction::DB::Artist;
58
59 use base 'DBIx::Class';
60 use Reaction::Class;
61
62 has 'artistid' => ( isa => 'Int', is => 'ro', required => 1 );
63 has 'name' => ( isa => 'NonEmptySimpleStr', is => 'rw', required => 1 );
64
65 sub display_name {
66 my $self = shift;
67 return $self->name;
68 }
69
70 __PACKAGE__->load_components(qw/PK::Auto Core/);
71 __PACKAGE__->table('artist');
72 __PACKAGE__->add_columns(qw/ artistid name /);
73 __PACKAGE__->set_primary_key('artistid');
74 __PACKAGE__->has_many( 'cds' => 'Test::Reaction::DB::Cd' );
75
76 1;
77
78DB/Cd.pm:
79
80 package Test::Reaction::DB::Cd;
81
82 use base 'DBIx::Class';
83 use Reaction::Class;
84
85 has 'cdid' => ( isa => 'Int', is => 'ro', required => 1 );
86 has 'artist' =>
87 ( isa => 'Test::Reaction::DB::Artist', is => 'rw', required => 1 );
88 has 'title' => ( isa => 'NonEmptySimpleStr', is => 'rw', required => 1 );
89
90 sub display_name {
91 my $self = shift;
92 return $self->title;
93 }
94
95 __PACKAGE__->load_components(qw/PK::Auto Core/);
96 __PACKAGE__->table('cd');
97 __PACKAGE__->add_columns(qw/ cdid artist title/);
98 __PACKAGE__->set_primary_key('cdid');
99 __PACKAGE__->belongs_to( 'artist' => 'Test::Reaction::DB::Artist' );
100 __PACKAGE__->has_many( 'tracks' => 'Test::Reaction::DB::Track' );
101
102 1;
103
104DB/Track.pm:
105
106 package Test::Reaction::DB::Track;
107
108 use base 'DBIx::Class';
109 use Reaction::Class;
110
111 has 'trackid' => ( isa => 'Int', is => 'ro', required => 1 );
112 has 'cd' => ( isa => 'Test::Reaction::DB::Cd', is => 'rw', required => 1 );
113 has 'title' => ( isa => 'NonEmptySimpleStr', is => 'rw', required => 1 );
114
115 __PACKAGE__->load_components(qw/PK::Auto Core/);
116 __PACKAGE__->table('track');
117 __PACKAGE__->add_columns(qw/ trackid cd title/);
118 __PACKAGE__->set_primary_key('trackid');
119 __PACKAGE__->belongs_to( 'cd' => 'Test::Reaction::DB::Cd' );
120
121 1;
122
123=head3 Reaction attributes
124
125See L<Reaction::Types::Core>
126
127=head3 The rest
128
129Reaction will use I<sub display_name> for displaying when there is a 1:Many or
130Many:Many relation. It will return a suitable text representation.
131
132=head2 Models
133
134=head3 Create Test::Reaction::Model::Action
135
136Still in lib/Test/Reaction, create
137
138Model/Action.pm:
139
140 package Test::Reaction::Model::Action;
141
142 use Reaction::Class;
143
144 use Test::Reaction::DB;
145
146 use aliased 'Reaction::InterfaceModel::Action::DBIC::ActionReflector';
147
148 my $r = ActionReflector->new;
149
150 $r->reflect_actions_for( 'Test::Reaction::DB::Artist' => __PACKAGE__ );
151 $r->reflect_actions_for( 'Test::Reaction::DB::Cd' => __PACKAGE__ );
152 $r->reflect_actions_for( 'Test::Reaction::DB::Track' => __PACKAGE__ );
153
154 1;
155
156=head2 Controllers
157
158Reaction controllers inherit from Reaction::UI::CRUDController, like this:
159
160Controller/Artist.pm
161
162 package Test::Reaction::Controller::Artist;
163
164 use strict;
165 use warnings;
166 use base 'Reaction::UI::CRUDController';
167 use Reaction::Class;
168
169 __PACKAGE__->config(
170 model_base => 'Test::Reaction',
171 model_name => 'Artist',
172 action => { base => { Chained => '/base', PathPart => 'artist' } }
173 );
174
175 1;
176
177Controller/Cd.pm
178
179 package Test::Reaction::Controller::Cd;
180
181 use strict;
182 use warnings;
183 use base 'Reaction::UI::CRUDController';
184 use Reaction::Class;
185
186 __PACKAGE__->config(
187 model_base => 'Test::Reaction',
188 model_name => 'Cd',
189 action => { base => { Chained => '/base', PathPart => 'cd' } }
190 );
191
192 1;
193
194Controller/Track.pm
195
196 package Test::Reaction::Controller::Track;
197
198 use strict;
199 use warnings;
200 use base 'Reaction::UI::CRUDController';
201 use Reaction::Class;
202
203 __PACKAGE__->config(
204 model_base => 'Test::Reaction',
205 model_name => 'Track',
206 action => { base => { Chained => '/base', PathPart => 'track' } }
207 );
208
209 1;
210
211Finally, change Controller/Root.pm to
212
213 package Test::Reaction::Controller::Root;
214
215 use strict;
216 use warnings;
217 use base 'Reaction::UI::RootController';
218 use Reaction::Class;
219
220 use aliased 'Reaction::UI::ViewPort';
221 use aliased 'Reaction::UI::ViewPort::ListView';
222 use aliased 'Reaction::UI::ViewPort::ActionForm';
223
224 __PACKAGE__->config->{namespace} = '';
225
226 sub base :Chained('/') :PathPart('') :CaptureArgs(0) {
227 my ($self, $c) = @_;
228
229 $self->push_viewport(ViewPort, layout => 'xhtml');
230 }
231
232 sub root :Chained('base') :PathPart('') :Args(0) {
233 my ($self, $c) = @_;
234
235 $self->push_viewport(ViewPort, layout => 'index');
236 }
237
238 1;
239
240=head2 View
241
242View/XHTML.pm looks like this
243
244 package Test::Reaction::View::XHTML;
245
246 use Reaction::Class;
247
248 extends 'Reaction::UI::Renderer::XHTML';
249
250 1;
251
252This is all the perly stuff. Now return to the base Test-Reaction directory and
253create root/index:
254
255 [%
256
257 main_block = 'index';
258
259 BLOCK index;
260
261 %]<p><a href="[% ctx.uri_for('/artist') %]">artist</a></p>
262 <p><a href="[% ctx.uri_for('/cd') %]">cd</a></p>
263 <p><a href="[% ctx.uri_for('/track') %]">track</a></p>[%
264
265 END;
266
267 %]
268
269=head2 Running
270
996236fb 271Now all that remains is to tell Catalyst about the root and the model. Let
1f9daa1e 272test_reaction.yml look like this:
273
274 ---
275 name: Test::Reaction
276 Controller::Root:
277 view_name: 'XHTML'
278 window_title: 'Reaction Test App'
279 Model::Test::Reaction:
280 schema_class: 'Test::Reaction::DB'
281 connect_info:
282 - 'dbi:SQLite:dbname=database/example.db'
283
284The finals step for this example is to link to Reaction's templates:
285
286 ln -s <path to reaction install directory>/root/base/ root/base
287
288At last you're now ready to run the server
289
290 script/test_reaction_server.pl
291
292=head1 Notes
293
294=head1 TODO
295
296=head1 AUTHORS
297
298See L<Reaction::Class> for authors.
299
300=head1 LICENSE
301
302See L<Reaction::Class> for the license.
303
304=cut