more pod fixes
[catagits/Reaction.git] / lib / Reaction / Manual / Tutorial.pod
CommitLineData
63bb30b4 1=head1 NAME
2
5c818114 3Reaction::Manual::Tutorial - Step by Step Tutorial
63bb30b4 4
5=head1 DESCRIPTION
6
7This document aims at giving simple step-by-step leading to an example application
8using the common functionality provided by L<Reaction>.
9
10=head1 CREATING A NEW APPLICATION
11
12At first we have to create a new application. For this we use the C<catalyst.pl>
13script as we would for any other Catalyst application:
14
15 $ catalyst.pl MyApp
16 [lots "created ..." messages]
17
18There is nothing to change in the application class file.
19
139b74f7 20As you work through this tutorial you'll be creating several new files in
21various directories. You can save some time by creating the directories now,
22like this:
23
24 mkdir -p share/skin/myapp/layout lib/MyApp/View/Site/Widget lib/MyApp/Schema lib/MyApp/InterfaceModel
25
63bb30b4 26=head1 THE VIEW
27
28Since we are not just rendering templates with Reaction, but layouts and widgets,
29a simple TT view won't suffice. We need to create our own C<lib/MyApp/View/Site.pm>:
30
31 package MyApp::View::Site;
32 use Reaction::Class;
33
91c2674b 34 use namespace::autoclean;
63bb30b4 35
36 extends 'Reaction::UI::View::TT';
37
38 __PACKAGE__->meta->make_immutable;
39
40 1;
41
42The C<use Reaction::Class> line will import L<Moose>, L<strict> and L<warnings> into
43our file and might perform some Reaction specific setups.
44
45We make sure that we don't provide imported functions as methods at runtime by using
91c2674b 46L<namespace::autoclean>.
63bb30b4 47
48In its simplest version, our view just needs to do a C<extends 'Reaction::UI::View::TT'>
49to make a new subclass of it.
50
51We chose to call C<make_immutable> on the class' meta class instance to have it inline
52methods for runtime speed improvements.
53
54=head1 THE ROOT CONTROLLER
55
56As usual in Catalyst, our root controller (at C<lib/MyApp/Controller/Root.pm> represents
57the root namespace for our application. For this purpose, it should look like this:
58
59 package MyApp::Controller::Root;
60 use strict;
61 use warnings;
62 use parent 'Reaction::UI::Controller::Root';
63
64 use aliased 'Reaction::UI::ViewPort';
65 use aliased 'Reaction::UI::ViewPort::SiteLayout';
66
91c2674b 67 use namespace::autoclean;
63bb30b4 68
69 __PACKAGE__->config(
70 view_name => 'Site',
71 window_title => 'MyApp Window',
72 namespace => '',
73 );
74
75 sub base: Chained('/') PathPart('') CaptureArgs(0) {
76 my ($self, $ctx) = @_;
77 $self->push_viewport(SiteLayout,
78 title => 'MyApp Test Title',
79 static_base_uri => join('', $ctx->uri_for('/static')),
158404c5 80 meta_info => {
81 http_header => {
82 'Content-Type' => 'text/html;charset=utf-8',
83 },
84 },
63bb30b4 85 );
86 }
87
88 sub root: Chained('base') PathPart('') Args(0) {
89 my ($self, $ctx) = @_;
90 $self->push_viewport(ViewPort, layout => 'root');
91 }
92
93 1;
94
91c2674b 95The effects of L<strict>, L<warnings>, L<parent>, L<aliased> and L<namespace::autoclean>
96should be clear by now. Let's take a look at the configuration.
63bb30b4 97
98The C<view_name> determines which view to use. We set it to C<Site>, which is our only view
99by now. Be careful to set C<view_name> and not C<view>, which would fail telling you it
100expected an object.
101
102The C<window_title> is the title given to the L<Reaction::UI::Window> instance that will be
103stored in C<$ctx-E<gt>stash-E<gt>{window}> by the C<begin> action provided by
104L<Reaction::UI::Controller::Root>.
105
106The C<namespace> setting anchors the root controller at C</>.
107
108The C<base> action here acts as a general point all other actions can chain off of. It
109pushes the L<Reaction::UI::ViewPort::SiteLayout> viewport onto the
110L<focus stack|Reaction::UI::FocusStack>. As arguments we see a C<title> that will be used
111as page title later. The C<static_base_uri> is used for static links like CSS and JavaScript
112files. Since we didn't specify a layout C<site_layout> will be used.
113
114We also defined a C<root> action serving as application index. It chains off the C<base>
115action. It is only pushing the root viewport L<Reaction::UI::ViewPort> on the focus stack,
116but this time we specified a layout named C<root>.
117
118Reaction will try to find our layout files in C<share/skin/$skin_name/layout/*>, so the next
119thing to do is to create a new skin and the layout files.
120
121=head1 A NEW SKIN
122
123If your version of Catalyst still creates a C<root> instead of a C<share> directory, you
124might want to rename it. This is regarded as a best practice and follows the conventions
125of this tutorial and other Reaction documentation.
126
127First we need to create a directory for our new skin:
128
129 $ mkdir -p share/skin/myapp/layout
130
131Next we need to configure our new skin. This is done in the C<share/skin/myapp/skin.conf>
132file. At the moment, all it should contain is
133
134 extends /Reaction/default
135
136Note that this C<extends> specification contains the distribution name of the
137library or application of which to use the templates as base. You can also give it
138a relative name like
139
140 extends foo
141
142and it would try to extend a skin named C<foo> in your own application's C<share/skin>
143directory.
144
753f8f1d 145In general, the Reaction distribution provides two skin choices to build upon:
146C</Reaction/default> and C</Reaction/base>. C<base> is Reaction's most basic skin
147while the C<default> skin extends the base by embellishing the layouts with more XHTML.
148The default skin is designed to be a working skin.
149
150In other words, if you want to write most of the low-level XHTML yourself
151then put the following in your skin.conf:
152
153 extends /Reaction/base
154
155If you want to use more XHTML out of the box, then configure your application to extend
156the default skin.
157
158It's worth noting that you are not bound to the XHTML of the default or base skin layouts,
159because you are able to override layout fragments in your own skin.
160
161Next we create C<share/skin/defaults.conf> to allow settings that concern all skins of
63bb30b4 162the application. It should contain only this:
163
164 widget_search_path MyApp::View::Site::Widget
165 widget_search_path Reaction::UI::Widget
166
167This will tell Reaction to look in C<Reaction::UI::Widget::*> and
168C<MyApp::View::Site::Widget::*> for widget classes. That means that our layout named
169C<root> will check for C<MyApp::View::Site::Widget::Root> first and then look if
170C<Reaction::UI::Widget> exists.
171
172We want the first line to be able to create our own widgets and the second line to
173have Reaction find its own widgets.
174
175Now we need to tell Reaction what skin it should use. We do this by adding this section
176to our C<myapp.conf>:
177
178 <View Site>
179 skin_name myapp
180 </View>
181
182The value should be the name of the target directory under C<share/skin/>.
183
184=head1 LAYOUTS
185
186We will need two layout files to begin with. One controlling the site layout and one
187for the root action.
188
189The first will be created as C<share/skin/myapp/layout/site_layout.tt>:
190
191 =extends NEXT
192
193 =for layout body
194
195 <h1>Welcome to MyApp</h1>
196
197 <div id="content">
198 [% inner %]
199 </div>
200
201 =cut
202
203The C<=extends> directive specifies that this layout file is an extension of another
204layout file. The C<NEXT> value here tells Reaction that this extends the C<site_layout>
205layout in the base skin, which we have defined as C</Reaction/default>. That means, you
206can take a look at the layout we are extending at C<share/skin/default/layout/site_layout.tt>
207in the L<Reaction> distribution.
208
209The C<=for layout> directives allows us to set a layout fragment. We define a C<body> fragment
210containing the common C<body> for all pages using this site layout. The C<[% inner %]> is
211where the deeper parts of the stack will be included, in the case of our C<root> action that
212would be the C<Reaction::UI::ViewPort> with the C<root> layout.
213
753f8f1d 214If we want to override a specific fragment, we can do just that. There are two choices
215when overriding a specific fragment. One can disregard the parent fragment all together
216and start from scratch or they could reuse the parent fragment and add to it. The key to
217re-using a parent (extended) layout fragment is the keyword C<call_next>. Specifically,
218we insert C<[% call_next %]> to include the layout fragment of the parent.
219
220The parent layout fragment is found either in another layout template named in the
221C<=extends> directive or it's in a subclass of Reaction::UI::Widget.
222In the latter case, the Widget subclass name matches the name of the template or
223the widget name posed at the top of the layout file via the C<=widget> directive.
224
225Once you know the hierarchy C<call_next> follows, then you know where to examine
226the details of the parent layouts or widgets.
63bb30b4 227
228The layout representing the root action is called C<share/skin/myapp/layout/root.tt>:
229
230 =for layout widget
231
232 <p>Hello, World!</p>
233
234 =cut
235
236This one is rather simple. The C<=for layout widget> directive is special in that the
237C<widget> fragment will always be where the rendering starts. In fact, our C<site_layout>
238layout too contains a C<widget> fragment, you just don't see it because you inherited it from
239your base skin (or your base skin's base skin, for that matter) instead of defining it yourself.
240
241=head1 A SIMPLE WIDGET
242
243If we wanted to use a different kind of widget than that assumed automatically by Reaction, we
244could add a
245
246 =widget ClassName
247
248directive at the top of the layout file. But for now, we will instead create our own
249widget at C<lib/MyApp/View/Site/Widget/Root.pm>:
250
251 package MyApp::View::Site::Widget::Root;
252 use Reaction::UI::WidgetClass;
253
91c2674b 254 use namespace::autoclean;
63bb30b4 255
256 __PACKAGE__->meta->make_immutable;
257
258 1;
259
260This adds no new functionality at the moment. It just uses C<Reaction::UI::WidgetClass> to ease
261and automate the setup of a new widget class. The widget can provide functionality and fragments
262to the layout. In a way, it can be seen as the Perl code backend to the layout file.
263
264You can now start your C<script/myapp_server.pl> and visit
265
266 http://localhost:3000/
267
268to view your "Hello, World" page.
269
270=head1 ADDING A SCHEMA
271
272The next part of the tutorial will be about adding data storage to our application. While most
273L<Catalyst> web applications today (or at least they should) abstract their database schema
274with L<DBIx::Class::Schema> into a separate module separated from the webapplication, Reaction
275takes this one step further by introducing so called interface models. The interface model
276defines the layer between your application and your domain model (in this case, the L<DBIx::Class>
277schema).
278
139b74f7 279The first thing we will need is a schema class in C<lib/MyApp/Schema.pm>:
63bb30b4 280
281 package MyApp::Schema;
282 use strict;
283 use warnings;
284
285 use parent 'DBIx::Class::Schema';
286
287 __PACKAGE__->load_classes;
288
289 1;
290
291The schema class itself is built like a typical L<DBIx::Class::Schema>. The difference in class
292definition starts at the result classes. For the example's sake, let's make a SQLite database
293called C<example.sqlite>:
294
295 $ cat > example.sqlite.sql
296 CREATE TABLE foo (
297 id INTEGER PRIMARY KEY AUTOINCREMENT,
298 first_name VARCHAR NOT NULL,
299 last_name VARCHAR NOT NULL
300 );
301 <Ctrl-D>
302
303 $ sqlite3 example.sqlite < example.sqlite.sql
304 $
305
306The result class for this table combines the usual style of L<DBIx::Class> with L<Moose> meta
139b74f7 307data additions in C<lib/MyApp/Schema/Foo.pm>:
63bb30b4 308
309 package MyApp::Schema::Foo;
310 use Moose;
311 use MooseX::Types::Moose qw( Int );
312 use Reaction::Types::Core qw( NonEmptySimpleStr );
313
91c2674b 314 use namespace::autoclean;
63bb30b4 315
316 extends 'DBIx::Class';
317
318 has id =>
319 (is => 'ro', isa => Int, required => 1);
320
321 has first_name =>
322 (is => 'rw', isa => NonEmptySimpleStr, required => 1);
323
324 has last_name =>
325 (is => 'rw', isa => NonEmptySimpleStr, required => 1);
326
327 __PACKAGE__->load_components(qw( IntrospectableM2M Core ));
328 __PACKAGE__->table('foo');
329
330 __PACKAGE__->add_columns(
331 id => {
332 data_type => 'integer',
333 is_auto_increment => 1,
334 },
335 first_name => { data_type => 'varchar' },
336 last_name => { data_type => 'varchar' },
337 );
338
339 __PACKAGE__->set_primary_key('id');
340
341 1;
342
343The L<MooseX::Types::Moose> and L<Reaction::Types::Core> modules export L<Moose> type
344constraints (See also L<MooseX::Types> and L<Moose::Util::TypeConstraints>). Note that
345we are using L<Moose/extends> here instead of L<base> or L<parent> to extend
346L<DBIx::Class>.
347
348Next we see our columns in form of Moose attribute definitions. The C<is>, C<isa> and
349C<required> attribute parameters will all be used for introspection and interface
350building later. The C<required> is rather straight-forward. The C<is> will decide whether
351this attribute (or column) can be edited (C<ro> means that it can't, C<rw> means it can).
352The C<isa> attribute will be used for validation and rendering of input fields.
353
354The imported C<NonEmptySimpleStr> for example gives us a simple single-line input box,
355while a C<Str> from L<MooseX::Types::Moose> would give us a textbox.
356
357Following that, we have the usual L<DBIx::Class> result class definitions. The only thing
358different might be the new L<DBIx::Class::IntrospectableM2M> which will allow us to
359inspect many-to-many relations later on.
360
361=head1 CREATING AN INTERFACE MODEL
362
363The interface model should be separated from the application and the schema, since it
364will tie both together. In this case, we will use a reflector to set up the usual interface
139b74f7 365model actions for our schema (C<Create>, C<Update>, C<Delete>, C<DeleteAll>) in
366C<lib/MyApp/InterfaceModel/DBIC.pm>:
63bb30b4 367
368 package MyApp::InterfaceModel::DBIC;
369
370 # keep this on top
371 use parent 'Reaction::InterfaceModel::Object';
372
373 use Reaction::Class;
374 use Reaction::InterfaceModel::Reflector::DBIC;
375
91c2674b 376 use namespace::autoclean;
63bb30b4 377
378 my $reflector = Reaction::InterfaceModel::Reflector::DBIC->new;
379
380 $reflector->reflect_schema(
381 model_class => __PACKAGE__,
382 schema_class => 'MyApp::Schema',
383 );
384
385 __PACKAGE__->meta->make_immutable;
386
387 1;
388
389The L<parent> import must happen before the L<Reaction::Class> one in this case. Other
390than that, the only thing we do here is create a new L<Reaction::InterfaceModel::Reflector::DBIC>
391and call C<reflect_schema> to build our C<MyApp::InterfaceModel::DBIC::*> namespace out of our
392C<MyApp::Schema>.
393
394=head1 TIEING THE INTERFACE MODEL TO THE APPLICATION
395
396Next on the list is the integration of our new interface model into our application. For
397this we create a simple catalyst model in C<lib/MyApp/Model/DBIC.pm>:
398
399 package MyApp::Model::DBIC;
400 use Reaction::Class;
401
91c2674b 402 use namespace::autoclean;
63bb30b4 403
404 extends 'Catalyst::Model::Reaction::InterfaceModel::DBIC';
405
406 __PACKAGE__->meta->make_immutable;
407
408 __PACKAGE__->config(
409 im_class => 'MyApp::InterfaceModel::DBIC',
410 db_dsn => 'dbi:SQLite:example.sqlite',
411 );
412
413 1;
414
415This model L<extends|Moose> the L<Catalyst::Model::Reaction::InterfaceModel::DBIC> base class
416shipped with Reaction. It's configuration must contain the C<im_class> naming our interface
0a0813dd 417model and the C<db_dsn>. If you're using a different kind of database then you
418may neeb to add config for C<db_user>, C<db_password>, and C<db_params>.
419All these get passed to the schema's connect() method.
420
421Of course, since this is Catalyst, all this can also easily be specified
63bb30b4 422via your application config file under the C<Model::DBIC> key.
423
424=head1 BUILDING A SIMPLE CRUD CONTROLLER
425
426Now, since we have defined our interface model as well as our domain model including meta
139b74f7 427data, it isn't very hard (at least not for us) to build a basic (but extendable)
428CRUD controller in C<lib/MyApp/Controller/Foo.pm>:
63bb30b4 429
430 package MyApp::Controller::Foo;
431 use strict;
432 use warnings;
433
434 use parent 'Reaction::UI::Controller::Collection::CRUD';
435 use Reaction::Class;
436
91c2674b 437 use namespace::autoclean;
63bb30b4 438
439 __PACKAGE__->config(
440 model_name => 'DBIC',
441 collection_name => 'Foo',
442 actions => {
443 base => { Chained => '/base', PathPart => 'foo' },
444 },
445 );
446
447 1;
448
449This controller subclasses L<Reaction::UI::Controller::Collection::CRUD>, which is itself a
450subclass of L<Reaction::UI::Controller::Collection>, a class to ease the creation of controllers
451who act on collections of things.
452
453As you can see, for the simplest case we don't need any code; we simply configure our controller.
454
455The C<model_name> is the name of our interface model sans the C<MyApp::Model::> prefix. This means
456this entry points to C<MyApp::Model::DBIC> in this case. The C<collection_name> is the name of
0a0813dd 457the collection in the specified interface model. For us, this would be C<Foo>, to match the result
63bb30b4 458class we created above and want to manage.
459
460The C<actions> part of the configuration is not Reaction, but rather Catalyst specific. This
461configures the actions inherited from L<Reaction::UI::Controller::Collection::CRUD>. For it to
462work, we only need to tell the C<base> action where to chain off from, and what C<PathPart>
463to use. We chain it to the C<base> action in our root controller. The C<foo> path part is rather
464obvious.
465
466Now you can restart your application and visit
467
468 http://localhost:3000/foo
469
470and you have a complete CRUD interface for C<Foo> with listing, viewing, creating, updating
471and deleting capabilities.
472
f9b32c83 473=head1 WHERE TO GO NEXT
474
475=over
476
477=item L<Reaction::Manual::Templates>
478
479When a viewport tries to render a layout, it will involve the view to figure out the corresponding
480template (or any other kind of GUI description) and render it. The template documentation is concerned
481mostly with the C<Reaction::UI::View::TT> implementation allowing the developer to use the L<Template>
482engine to render the layouts.
483
484=item L<Reaction::Manual::Widgets>
485
486A widget is the backend Perl object providing the Perl view logic to a layout. What the rendered
487output actually looks like is determined by the layout. The widget is concerned with storing, providing
488and managing data used and rendered by the layout.
489
490=back
491
63bb30b4 492=head1 SEE ALSO
493
494=over
495
496=item * L<Reaction::Manual>
497
498=item * L<Reaction::Manual::Intro>
499
500=item * L<Reaction::Manual::Overview>
501
502=item * L<Reaction::Manual::Templates>
503
504=item * L<Reaction::Manual::RenderPage>
505
506=item * L<Reaction::UI::View::TT>
507
508=item * L<Reaction::UI::Controller::Root>
509
510=item * L<Reaction::UI::WidgetClass>
511
512=back
513
514=head1 AUTHORS
515
516See L<Reaction::Class> for authors.
517
518=head1 LICENSE
519
520See L<Reaction::Class> for the license.
521
522=cut