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