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