ec2 images, and some typo corrections
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / Tutorial / MoreCatalystBasics.pod
CommitLineData
3533daff 1=head1 NAME
2
3Catalyst::Manual::Tutorial::MoreCatalystBasics - Catalyst Tutorial - Part 3: More Catalyst Application Development Basics
4
5
6=head1 OVERVIEW
7
8This is B<Part 3 of 10> for the Catalyst tutorial.
9
10L<Tutorial Overview|Catalyst::Manual::Tutorial>
11
12=over 4
13
14=item 1
15
16L<Introduction|Catalyst::Manual::Tutorial::Intro>
17
18=item 2
19
20L<Catalyst Basics|Catalyst::Manual::Tutorial::CatalystBasics>
21
22=item 3
23
24B<More Catalyst Basics>
25
26=item 4
27
28L<Basic CRUD|Catalyst::Manual::Tutorial::BasicCRUD>
29
30=item 5
31
32L<Authentication|Catalyst::Manual::Tutorial::Authentication>
33
34=item 6
35
36L<Authorization|Catalyst::Manual::Tutorial::Authorization>
37
38=item 7
39
40L<Debugging|Catalyst::Manual::Tutorial::Debugging>
41
42=item 8
43
44L<Testing|Catalyst::Manual::Tutorial::Testing>
45
46=item 9
47
48L<Advanced CRUD|Catalyst::Manual::Tutorial::AdvancedCRUD>
49
50=item 10
51
52L<Appendices|Catalyst::Manual::Tutorial::Appendices>
53
54=back
55
56
57=head1 DESCRIPTION
58
59This part of the tutorial builds on the work done in Part 2 to explore
60some features that are more typical of "real world" web applications.
61From this part of the tutorial onward, we will be building a simple
62book database application. Although the application will be too
63limited to be of use to anyone, it should provide a basic environment
64where we can explore a variety of features used in virtually all web
65applications.
66
67You can checkout the source code for this example from the catalyst
68subversion repository as per the instructions in
69L<Catalyst::Manual::Tutorial::Intro>
70
71
72=head1 CREATE A NEW APPLICATION
73
74The remainder of the tutorial will build an application call C<MyApp>.
75Use the Catalyst C<catalyst.pl> script to initialize the framework for
76an application called C<MyApp> (make sure you aren't still inside the
77directory of the C<Hello> application from the previous part of the
78tutorial):
79
80 $ catalyst.pl MyApp
81 created "MyApp"
82 created "MyApp/script"
83 created "MyApp/lib"
84 created "MyApp/root"
85 ...
86 created "MyApp/script/myapp_create.pl"
87 $ cd MyApp
88
89This creates a similar skeletal structure to what we saw in Part 2 of
8a7c5151 90the tutorial, except with C<MyApp> and C<myapp> substituted for
3533daff 91C<Hello> and C<hello>.
92
93
94=head1 EDIT THE LIST OF CATALYST PLUGINS
95
96One of the greatest benefits of Catalyst is that it has such a large
97library of plugins available. Plugins are used to seamlessly integrate
98existing Perl modules into the overall Catalyst framework. In general,
99they do this by adding additional methods to the C<context> object
100(generally written as C<$c>) that Catalyst passes to every component
101throughout the framework.
102
103By default, Catalyst enables three plugins/flags:
104
105=over 4
106
107=item *
108
109C<-Debug> Flag
110
111Enables the Catalyst debug output you saw when we started the
112C<script/myapp_server.pl> development server earlier. You can remove
113this plugin when you place your application into production.
114
115As you may have noticed, C<-Debug> is not a plugin, but a I<flag>.
116Although most of the items specified on the C<use Catalyst> line of your
117application class will be plugins, Catalyst supports a limited number of
118flag options (of these, C<-Debug> is the most common). See the
119documentation for C<Catalyst.pm> to get details on other flags
120(currently C<-Engine>, C<-Home>, and C<-Log>).
121
122If you prefer, you can use the C<$c-E<gt>debug> method to enable debug
123messages.
124
125B<TIP>: Depending on your needs, it can be helpful to permanently
126remove C<-Debug> from C<lib/MyApp.pm> and then use the C<-d> option
127to C<script/myapp_server.pl> to re-enable it just for the development
128server. We will not be using that approach in the tutorial, but feel
129free to make use of it in your own projects.
130
131=item *
132
133L<Catalyst::Plugin::ConfigLoader|Catalyst::Plugin::ConfigLoader>
134
135C<ConfigLoader> provides an automatic way to load configurable
c010ae0d 136parameters for your application from a central
137L<Config::General|Config::General> file (versus having the values
138hard-coded inside your Perl modules). Config::General uses syntax
139very similar to Apache configuration files. We will see how to use
140this feature of Catalyst during the authentication and authorization
141sections (Part 5 and Part 6).
3533daff 142
d0496197 143B<IMPORTANT NOTE:> If you are following along in Ubuntu 8.04 or
056394af 144otherwise using a version of L<Catalyst::Devel|Catalyst::Devel> prior
145to version 1.06, you need to be aware that Catalyst changed from a
146default format of YAML to the more straightforward C<Config::General>
147format. Because Catalyst has long supported both formats, this
148tutorial will simply use a configuration file called C<myapp.conf>
149instead of C<myapp.yml> and Catatlyst will automcatically use the new
150format. Just be aware that earlier versions of Catalyst will still
151create the C<myapp.yml> file and that you will need to B<remove
152C<myapp.yml>> and create a new C<myapp.conf> file by hand, but
153otherwise this transition is very painless. The default contents of
154C<myapp.conf> should only consist of one line: C<name MyApp>. Also be
155aware that you can continue to use any format supported by
156L<Catalyst::Plugin::ConfigLoader|Catalyst::Plugin::ConfigLoader> and
157L<Config::Any|Config::Any>, including YAML -- Catalyst will
158automatically look for any of the supported configuration file
159formats.
15e1d0b2 160
d0496197 161B<TIP>: This script can be useful for converting between configuration
15e1d0b2 162formats:
163
164 perl -Ilib -e 'use MyApp; use Config::General;
165 Config::General->new->save_file("myapp.conf", MyApp->config);'
166
d0496197 167B<NOTE:> The default C<myapp.conf> should look like:
168
169 name MyApp
15e1d0b2 170
3533daff 171=item *
172
173L<Catalyst::Plugin::Static::Simple|Catalyst::Plugin::Static::Simple>
174
175C<Static::Simple> provides an easy method of serving static content such
176as images and CSS files under the development server.
177
178=back
179
180To modify the list of plugins, edit C<lib/MyApp.pm> (this file is
181generally referred to as your I<application class>) and delete the line
182with:
183
8a7c5151 184 __PACKAGE__->setup(qw/-Debug ConfigLoader Static::Simple/);
3533daff 185
186Replace it with:
187
8a7c5151 188 __PACKAGE__->setup(qw/
3533daff 189 -Debug
190 ConfigLoader
191 Static::Simple
192
193 StackTrace
8a7c5151 194 /);
3533daff 195
196This tells Catalyst to start using one new plugin:
197
198=over 4
199
200=item *
201
202L<Catalyst::Plugin::StackTrace|Catalyst::Plugin::StackTrace>
203
204Adds a stack trace to the standard Catalyst "debug screen" (this is the
205screen Catalyst sends to your browser when an error occurs).
206
207Note: L<StackTrace|Catalyst::Plugin::StackTrace> output appears in your
208browser, not in the console window from which you're running your
209application, which is where logging output usually goes.
210
cca5cd98 211B<Note:> You will want to disable
212L<StackTrace|Catalyst::Plugin::StackTrace> before you put your
213application into production, but it can be helpful during development.
214
3533daff 215=back
216
217Note that when specifying plugins on the C<use Catalyst> line, you can
218omit C<Catalyst::Plugin::> from the name. Additionally, you can spread
219the plugin names across multiple lines as shown here, or place them all
220on one (or more) lines as with the default configuration.
221
222
223=head1 CREATE A CATALYST CONTROLLER
224
225As discussed earlier, controllers are where you write methods that
226interact with user input. Typically, controller methods respond to
227C<GET> and C<POST> messages from the user's web browser.
228
229Use the Catalyst C<create> script to add a controller for book-related
230actions:
231
232 $ script/myapp_create.pl controller Books
233 exists "/home/me/MyApp/script/../lib/MyApp/Controller"
234 exists "/home/me/MyApp/script/../t"
235 created "/home/me/MyApp/script/../lib/MyApp/Controller/Books.pm"
236 created "/home/me/MyApp/script/../t/controller_Books.t"
237
238Then edit C<lib/MyApp/Controller/Books.pm> and add the following method
239to the controller:
240
241 =head2 list
242
243 Fetch all book objects and pass to books/list.tt2 in stash to be displayed
244
245 =cut
246
247 sub list : Local {
248 # Retrieve the usual Perl OO '$self' for this object. $c is the Catalyst
249 # 'Context' that's used to 'glue together' the various components
250 # that make up the application
251 my ($self, $c) = @_;
252
253 # Retrieve all of the book records as book model objects and store in the
254 # stash where they can be accessed by the TT template
d0496197 255 $c->stash->{books} = [$c->model('DB::Books')->all];
3533daff 256
257 # Set the TT template to use. You will almost always want to do this
258 # in your action methods (action methods respond to user input in
259 # your controllers).
260 $c->stash->{template} = 'books/list.tt2';
261 }
262
263B<Note:> This won't actually work yet since you haven't set up your
d0496197 264model yet. We will be covering the model soon.
3533daff 265
266B<Note:> Programmers experienced with object-oriented Perl should
267recognize C<$self> as a reference to the object where this method was
268called. On the other hand, C<$c> will be new to many Perl programmers
269who have not used Catalyst before (it's sometimes written as
270C<$context>). The Context object is automatically passed to all
271Catalyst components. It is used to pass information between
272components and provide access to Catalyst and plugin functionality.
273
d0496197 274B<TIP>: You may see the C<$c-E<gt>model('DB::Book')> used above
0c51850e 275written as C<$c-E<gt>model('DB')-E<gt>resultset('Book')>. The two
3533daff 276are equivalent.
277
278B<Note:> Catalyst actions are regular Perl methods, but they make use
279of Nicholas Clark's C<attributes> module (that's the C<: Local> next
280to the C<sub list> in the code above) to provide additional
281information to the Catalyst dispatcher logic. Many newer Catalyst
ae492862 282applications are switching to the use of "Literal" C<:Path> actions
3533daff 283and C<Args> attribute in lieu of C<: Local> and C<: Private>. For
ae492862 284example, C<sub any_method :Path :Args(0)> can be used instead of
3533daff 285C<sub index :Private> (because no path was supplied to C<Path> it
286matches the "empty" URL in the namespace of that module... the same
ae492862 287thing C<sub index> would do) or C<sub list :Path('list') :Args(0)>
3533daff 288could be used instead of the C<sub list : Local> above (the C<list>
289argument to C<Path> would make it match on the URL C<list> under
290C<books>, the namespace of the current module). See "Action Types" in
291L<Catalyst::Manual::Intro|Catalyst::Manual::Intro> as well as Part 5
292of this tutorial (Authentication) for additional information. Another
293popular but more advanced feature is C<Chained> actions that allow a
294single URL to "chain together" multiple action method calls, each with
295an appropriate number of arguments (see
296L<Catalyst::DispatchType::Chained|Catalyst::DispatchType::Chained>
297for details).
298
299
300=head1 CATALYST VIEWS
301
302As mentioned in Part 2 of the tutorial, views are where you render
303output, typically for display in the user's web browser, but also
304possibly using other display output- generation systems. As with
305virtually every aspect of Catalyst, options abound when it comes to
306the specific view technology you adopt inside your application.
307However, most Catalyst applications use the Template Toolkit, known as
d0496197 308TT (for more information on TT, see
309L<http://www.template-toolkit.org>). Other popular view technologies
310include Mason (L<http://www.masonhq.com> and
311L<http://www.masonbook.com>) and L<HTML::Template>
0c51850e 312(L<http://html-template.sourceforge.net>).
3533daff 313
314=head2 Create a Catalyst View Using C<TTSite>
315
316When using TT for the Catalyst view, there are two main helper scripts:
317
318=over 4
319
320=item *
321
322L<Catalyst::Helper::View::TT|Catalyst::Helper::View::TT>
323
324=item *
325
326L<Catalyst::Helper::View::TTSite|Catalyst::Helper::View::TTSite>
327
328=back
329
330Both are similar, but C<TT> merely creates the C<lib/MyApp/View/TT.pm>
331file and leaves the creation of any hierarchical template organization
332entirely up to you. (It also creates a C<t/view_TT.t> file for testing;
333test cases will be discussed in Part 8). The C<TTSite> helper creates a
334modular and hierarchical view layout with separate Template Toolkit (TT)
335files for common header and footer information, configuration values, a
336CSS stylesheet, and more.
337
338While TTSite is useful to bootstrap a project, we recommend that
339unless you know what you're doing or want to pretty much use the
340supplied templates as is, that you use the plain Template Toolkit view
341when starting a project from scratch. This is because TTSite can be
342tricky to customize. Additionally TT contains constructs that you
343need to learn yourself if you're going to be a serious user of TT.
344Our experience suggests that you're better off learning these from
345scratch. We use TTSite here precisely because it is useful for
346bootstrap/prototype purposes.
347
348Enter the following command to enable the C<TTSite> style of view
349rendering for this tutorial:
350
351 $ script/myapp_create.pl view TT TTSite
352 exists "/home/me/MyApp/script/../lib/MyApp/View"
353 exists "/home/me/MyApp/script/../t"
354 created "/home/me/MyApp/script/../lib/MyApp/View/TT.pm"
355 created "/home/me/MyApp/script/../root/lib"
356 ...
357 created "/home/me/MyApp/script/../root/src/ttsite.css"
358
359This puts a number of files in the C<root/lib> and C<root/src>
360directories that can be used to customize the look and feel of your
361application. Also take a look at C<lib/MyApp/View/TT.pm> for config
362values set by the C<TTSite> helper.
363
3533daff 364B<TIP>: When troubleshooting TT it can be helpful to enable variable
365C<DEBUG> options. You can do this in a Catalyst environment by adding
366a C<DEBUG> line to the C<__PACKAGE__->config> declaration in
367C<lib/MyApp/View/TT.pm>:
368
369 __PACKAGE__->config({
3533daff 370 ...
371 DEBUG => 'undef',
372 ...
373 });
374
375B<Note:> C<__PACKAGE__> is just a shorthand way of referencing the name
376of the package where it is used. Therefore, in C<TT.pm>,
377C<__PACKAGE__> is equivalent to C<TT>.
378
379There are a variety of options you can use, such as 'undef', 'all',
0c51850e 380'service', 'context', 'parser' and 'provider'. See
3533daff 381L<Template::Constants> for more information (remove the C<DEBUG_>
382portion of the name shown in the TT docs and convert to lower case
383for use inside Catalyst).
384
385B<NOTE:> B<Please be sure to disable TT debug options before
386continuing the tutorial> (especially the 'undef' option -- leaving
387this enabled will conflict with several of the conventions used
388by this tutorial and TTSite to leave some variables undefined
389on purpose).
390
391
392=head2 Globally Customize Every View
393
394When using TTSite, files in the subdirectories of C<root/lib> can be
395used to make changes that will appear in every view. For example, to
396display optional status and error messages in every view, edit
397C<root/lib/site/layout>, updating it to match the following (the two HTML
398C<span> elements are new):
399
400 <div id="header">[% PROCESS site/header %]</div>
401
402 <div id="content">
403 <span class="message">[% status_msg %]</span>
404 <span class="error">[% error_msg %]</span>
405 [% content %]
406 </div>
407
408 <div id="footer">[% PROCESS site/footer %]</div>
409
410If we set either message in the Catalyst stash (e.g.,
411C<$c-E<gt>stash-E<gt>{status_msg} = 'Request was successful!'>) it will
412be displayed whenever any view used by that request is rendered. The
413C<message> and C<error> CSS styles are automatically defined in
414C<root/src/ttsite.css> and can be customized to suit your needs.
415
416B<Note:> The Catalyst stash only lasts for a single HTTP request. If
417you need to retain information across requests you can use
418L<Catalyst::Plugin::Session|Catalyst::Plugin::Session> (we will use
419Catalyst sessions in the Authentication part of the tutorial).
420
421
422=head2 Create a TT Template Page
423
424To add a new page of content to the TTSite view hierarchy, just create a
425new C<.tt2> file in C<root/src>. Only include HTML markup that goes
426inside the HTML <body> and </body> tags, TTSite will use the contents of
427C<root/lib/site> to add the top and bottom.
428
429First create a directory for book-related TT templates:
430
431 $ mkdir root/src/books
432
433Then create C<root/src/books/list.tt2> in your editor and enter:
434
435 [% # This is a TT comment. The '-' at the end "chomps" the newline. You won't -%]
436 [% # see this "chomping" in your browser because HTML ignores blank lines, but -%]
437 [% # it WILL eliminate a blank line if you view the HTML source. It's purely -%]
438 [%- # optional, but both the beginning and the ending TT tags support chomping. -%]
439
440 [% # Provide a title to root/lib/site/header -%]
441 [% META title = 'Book List' -%]
442
443 <table>
444 <tr><th>Title</th><th>Rating</th><th>Author(s)</th></tr>
445 [% # Display each book in a table row %]
446 [% FOREACH book IN books -%]
447 <tr>
448 <td>[% book.title %]</td>
449 <td>[% book.rating %]</td>
450 </tr>
451 [% END -%]
452 </table>
453
454As indicated by the inline comments above, the C<META title> line uses
455TT's META feature to provide a title to C<root/lib/site/header>.
456Meanwhile, the outer C<FOREACH> loop iterates through each C<book> model
457object and prints the C<title> and C<rating> fields. An inner
458C<FOREACH> loop prints the last name of each author in a comma-separated
459list within a single table cell.
460
461If you are new to TT, the C<[%> and C<%]> tags are used to delimit TT
462code. TT supports a wide variety of directives for "calling" other
463files, looping, conditional logic, etc. In general, TT simplifies the
464usual range of Perl operators down to the single dot (C<.>) operator.
465This applies to operations as diverse as method calls, hash lookups, and
466list index values (see
467L<http://www.template-toolkit.org/docs/default/Manual/Variables.html>
468for details and examples). In addition to the usual C<Template> module
469Pod documentation, you can access the TT manual at
470L<http://www.template-toolkit.org/docs/default/>.
471
d0496197 472B<NOTE:> The C<TTSite> helper creates several TT files using an
3533daff 473extension of C<.tt2>. Most other Catalyst and TT examples use an
474extension of C<.tt>. You can use either extension (or no extension at
475all) with TTSite and TT, just be sure to use the appropriate extension
476for both the file itself I<and> the C<$c-E<gt>stash-E<gt>{template} =
477...> line in your controller. This document will use C<.tt2> for
478consistency with the files already created by the C<TTSite> helper.
479
480
481=head1 CREATE A SQLITE DATABASE
482
483In this step, we make a text file with the required SQL commands to
484create a database table and load some sample data. Open C<myapp01.sql>
485in your editor and enter:
486
487 --
488 -- Create a very simple database to hold book and author information
489 --
490 CREATE TABLE books (
491 id INTEGER PRIMARY KEY,
492 title TEXT ,
493 rating INTEGER
494 );
495 -- 'book_authors' is a many-to-many join table between books & authors
496 CREATE TABLE book_authors (
497 book_id INTEGER,
498 author_id INTEGER,
499 PRIMARY KEY (book_id, author_id)
500 );
501 CREATE TABLE authors (
502 id INTEGER PRIMARY KEY,
503 first_name TEXT,
504 last_name TEXT
505 );
506 ---
507 --- Load some sample data
508 ---
509 INSERT INTO books VALUES (1, 'CCSP SNRS Exam Certification Guide', 5);
510 INSERT INTO books VALUES (2, 'TCP/IP Illustrated, Volume 1', 5);
511 INSERT INTO books VALUES (3, 'Internetworking with TCP/IP Vol.1', 4);
512 INSERT INTO books VALUES (4, 'Perl Cookbook', 5);
513 INSERT INTO books VALUES (5, 'Designing with Web Standards', 5);
514 INSERT INTO authors VALUES (1, 'Greg', 'Bastien');
515 INSERT INTO authors VALUES (2, 'Sara', 'Nasseh');
516 INSERT INTO authors VALUES (3, 'Christian', 'Degu');
517 INSERT INTO authors VALUES (4, 'Richard', 'Stevens');
518 INSERT INTO authors VALUES (5, 'Douglas', 'Comer');
519 INSERT INTO authors VALUES (6, 'Tom', 'Christiansen');
520 INSERT INTO authors VALUES (7, 'Nathan', 'Torkington');
521 INSERT INTO authors VALUES (8, 'Jeffrey', 'Zeldman');
522 INSERT INTO book_authors VALUES (1, 1);
523 INSERT INTO book_authors VALUES (1, 2);
524 INSERT INTO book_authors VALUES (1, 3);
525 INSERT INTO book_authors VALUES (2, 4);
526 INSERT INTO book_authors VALUES (3, 5);
527 INSERT INTO book_authors VALUES (4, 6);
528 INSERT INTO book_authors VALUES (4, 7);
529 INSERT INTO book_authors VALUES (5, 8);
530
531B<TIP>: See Appendix 1 for tips on removing the leading spaces when
532cutting and pasting example code from POD-based documents.
533
534Then use the following command to build a C<myapp.db> SQLite database:
535
536 $ sqlite3 myapp.db < myapp01.sql
537
538If you need to create the database more than once, you probably want to
539issue the C<rm myapp.db> command to delete the database before you use
540the C<sqlite3 myapp.db < myapp01.sql> command.
541
542Once the C<myapp.db> database file has been created and initialized, you
543can use the SQLite command line environment to do a quick dump of the
544database contents:
545
546 $ sqlite3 myapp.db
547 SQLite version 3.4.2
548 Enter ".help" for instructions
549 sqlite> select * from books;
550 1|CCSP SNRS Exam Certification Guide|5
551 2|TCP/IP Illustrated, Volume 1|5
552 3|Internetworking with TCP/IP Vol.1|4
553 4|Perl Cookbook|5
554 5|Designing with Web Standards|5
555 sqlite> .q
556 $
557
558Or:
559
560 $ sqlite3 myapp.db "select * from books"
561 1|CCSP SNRS Exam Certification Guide|5
562 2|TCP/IP Illustrated, Volume 1|5
563 3|Internetworking with TCP/IP Vol.1|4
564 4|Perl Cookbook|5
565 5|Designing with Web Standards|5
566
567As with most other SQL tools, if you are using the full "interactive"
568environment you need to terminate your SQL commands with a ";" (it's not
569required if you do a single SQL statement on the command line). Use
570".q" to exit from SQLite from the SQLite interactive mode and return to
571your OS command prompt.
572
573
574=head1 DATABASE ACCESS WITH C<DBIx::Class>
575
576Catalyst can be used with virtually any form of persistent datastore
577available via Perl. For example,
578L<Catalyst::Model::DBI|Catalyst::Model::DBI> can be used to
579easily access databases through the traditional Perl C<DBI> interface.
580However, most Catalyst applications use some form of ORM technology to
581automatically create and save model objects as they are used. Although
582Tony Bowden's L<Class::DBI|Class::DBI> has been a popular choice
583in the past, Matt Trout's L<DBIx::Class|DBIx::Class> (abbreviated
584as "DBIC") has rapidly emerged as the Perl-based ORM technology of choice.
585Most new Catalyst applications rely on DBIC, as will this tutorial.
586
bb2dbfb8 587=head2 Create a dynamic DBIC Model
3533daff 588
bb2dbfb8 589Use the C<create=dynamic> model helper option to build a model that
3533daff 590dynamically reads your database structure every time the application
591starts:
592
d0496197 593 $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema create=dynamic dbi:SQLite:myapp.db
594 exists "/home/kclark/dev/MyApp/script/../lib/MyApp/Model"
595 exists "/home/kclark/dev/MyApp/script/../t"
596 exists "/home/kclark/dev/MyApp/script/../lib/MyApp"
597 created "/home/kclark/dev/MyApp/script/../lib/MyApp/Schema.pm"
598 created "/home/kclark/dev/MyApp/script/../lib/MyApp/Model/DB.pm"
599 created "/home/kclark/dev/MyApp/script/../t/model_DB.t"
3533daff 600
601
d0496197 602C<DB> is the name of the model class to be created by the helper in
3533daff 603C<lib/MyApp/Model> (Catalyst has a separate directory under C<lib/MyApp>
d0496197 604for each of the three parts of MVC: C<Model>, C<View>, and C<Controller>).
605C<DBIC::Schema> is the type of the model to create.
606C<MyApp::Schema> is the name of the DBIC schema file written to
607C<lib/MyApp/Schema.pm>. Because we specified C<create=dynamic>
3533daff 608to the helper, it use L<DBIx::Class::Schema::Loader> to dynamically load
609the schema information from the database every time the application
610starts. And finally, C<dbi:SQLite:myapp.db> is the standard DBI connect
611string for use with SQLite.
612
d0496197 613B<NOTE:> Although the C<create=dynamic> option to the DBIC helper
19c49089 614makes for a nifty demonstration, is only really suitable for very
615small applications. After this demonstration, you should almost always
616use the C<create=static> option that we switch to below.
dc9a0503 617
618
3533daff 619=head1 RUN THE APPLICATION
620
621First, let's enable an environment variable option that causes
622DBIx::Class to dump the SQL statements it's using to access the database
623(this option can provide extremely helpful troubleshooting information):
624
625 $ export DBIC_TRACE=1
626
627This assumes you are using BASH as your shell -- adjust accordingly if
628you are using a different shell (for example, under tcsh, use
629C<setenv DBIC_TRACE 1>).
630
d0496197 631B<NOTE:> You can also set this in your code using
3533daff 632C<$class-E<gt>storage-E<gt>debug(1);>. See
633L<DBIx::Class::Manual::Troubleshooting> for details (including options
634to log to file instead of displaying to the Catalyst development server
635log).
636
637Then run the Catalyst "demo server" script:
638
639 $ script/myapp_server.pl
640
641Your development server log output should display something like:
642
643 $script/myapp_server.pl
644 [debug] Debug messages enabled
645 [debug] Loaded plugins:
646 .----------------------------------------------------------------------------.
647 | Catalyst::Plugin::ConfigLoader 0.17 |
648 | Catalyst::Plugin::StackTrace 0.06 |
649 | Catalyst::Plugin::Static::Simple 0.20 |
650 '----------------------------------------------------------------------------'
651
652 [debug] Loaded dispatcher "Catalyst::Dispatcher"
653 [debug] Loaded engine "Catalyst::Engine::HTTP"
654 [debug] Found home "/home/me/MyApp"
45d511e0 655 [debug] Loaded Config "/home/me/MyApp/myapp.conf"
3533daff 656 [debug] Loaded components:
657 .-----------------------------------------------------------------+----------.
658 | Class | Type |
659 +-----------------------------------------------------------------+----------+
660 | MyApp::Controller::Books | instance |
661 | MyApp::Controller::Root | instance |
d0496197 662 | MyApp::Model::DB | instance |
663 | MyApp::Model::DB::Authors | class |
664 | MyApp::Model::DB::BookAuthors | class |
665 | MyApp::Model::DB::Books | class |
3533daff 666 | MyApp::View::TT | instance |
667 '-----------------------------------------------------------------+----------'
668
669 [debug] Loaded Private actions:
670 .----------------------+--------------------------------------+--------------.
671 | Private | Class | Method |
672 +----------------------+--------------------------------------+--------------+
673 | /default | MyApp::Controller::Root | default |
674 | /end | MyApp::Controller::Root | end |
675 | /books/index | MyApp::Controller::Books | index |
676 | /books/list | MyApp::Controller::Books | list |
677 '----------------------+--------------------------------------+--------------'
678
679 [debug] Loaded Path actions:
680 .-------------------------------------+--------------------------------------.
681 | Path | Private |
682 +-------------------------------------+--------------------------------------+
683 | /books/list | /books/list |
684 '-------------------------------------+--------------------------------------'
685
686 [info] MyApp powered by Catalyst 5.7011
687 You can connect to your server at http://localhost:3000
688
d0496197 689B<NOTE:> Be sure you run the C<script/myapp_server.pl> command from
3533daff 690the 'base' directory of your application, not inside the C<script>
691directory itself or it will not be able to locate the C<myapp.db>
692database file. You can use a fully qualified or a relative path to
693locate the database file, but we did not specify that when we ran the
694model helper earlier.
695
696Some things you should note in the output above:
697
698=over 4
699
700=item *
701
702Catalyst::Model::DBIC::Schema dynamically created three model classes,
703one to represent each of the three tables in our database
d0496197 704(C<MyApp::Model::DB::Authors>, C<MyApp::Model::DB::BookAuthors>,
705and C<MyApp::Model::DB::Books>).
3533daff 706
707=item *
708
709The "list" action in our Books controller showed up with a path of
710C</books/list>.
711
712=back
713
714Point your browser to L<http://localhost:3000> and you should still get
715the Catalyst welcome page.
716
717Next, to view the book list, change the URL in your browser to
718L<http://localhost:3000/books/list>. You should get a list of the five
719books loaded by the C<myapp01.sql> script above, with TTSite providing
720the formatting for the very simple output we generated in our template.
721The rating for each book should appear on each row.
722
723Also notice in the output of the C<script/myapp_server.pl> that DBIC
724used the following SQL to retrieve the data:
725
726 SELECT me.id, me.title, me.rating FROM books me
727
728because we enabled DBIC_TRACE.
729
0c51850e 730You now have the beginnings of a simple but workable web application.
3533daff 731Continue on to future sections and we will develop the application
732more fully.
733
734
735=head1 A STATIC DATABASE MODEL WITH C<DBIx::Class>
736
737=head2 Create Static DBIC Schema Files
738
739Unlike the previous section where we had DBIC automatically discover the
740structure of the database every time the application started, here we
741will use static schema files for more control. This is typical of most
742"real world" applications.
743
744One option would be to create a separate schema file for each table in
745the database, however, lets use the same L<DBIx::Class::Schema::Loader>
746used earlier with C<create=dynamic> to build the static files for us.
9ad715b3 747First, lets remove the schema file created earlier:
3533daff 748
d0496197 749 $ rm lib/MyApp/Schema.pm
3533daff 750
751Now regenerate the schema using the C<create=static> option:
752
d0496197 753 $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema create=static dbi:SQLite:myapp.db
754 exists "/home/kclark/dev/MyApp/script/../lib/MyApp/Model"
755 exists "/home/kclark/dev/MyApp/script/../t"
756 Dumping manual schema for MyApp::Schema to directory /home/kclark/dev/MyApp/script/../lib ...
3533daff 757 Schema dump completed.
d0496197 758 exists "/home/kclark/dev/MyApp/script/../lib/MyApp/Model/DB.pm"
3533daff 759
d0496197 760We could have also deleted C<lib/MyApp/Model/DB.pm>, but it would
3533daff 761have regenerated the same file (note the C<exists> in the output above).
d0496197 762If you take a look at C<lib/MyApp/Model/DB.pm>, it simply contains
763a reference to the actual schema file in C<lib/MyApp/Schema.pm>
3533daff 764along with the database connect string.
765
766If you look in the C<lib/MyApp/Schema> directory, you will find that
d0496197 767C<DB.pm> is no longer using L<DBIx::Class::Schema::Loader> as its
3533daff 768base class (L<DBIx::Class::Schema::Loader> is only being used by the
769helper to load the schema once and then create the static files for us)
770and that it only contains a call to the C<load_classes> method. You
d0496197 771will also find that C<lib/MyApp/Schema> contains a C<Schema>
3533daff 772subdirectory, with one file inside this directory for each of the tables
773in our simple database (C<Authors.pm>, C<BookAuthors.pm>, and
774C<Books.pm>). These three files were created based on the information
775found by L<DBIx::Class::Schema::Loader> as the helper ran.
776
777The idea with all of the files created under C<lib/MyApp/Schema> by the
778C<create=static> option is to only edit the files below the C<# DO NOT
779MODIFY THIS OR ANYTHING ABOVE!> warning. If you place all of your
780changes below that point in the file, you can regenerate the
781auto-generated information at the top of each file should your database
782structure get updated.
783
784Also note the "flow" of the model information across the various files
785and directories. Catalyst will initially load the model from
d0496197 786C<lib/MyApp/Model/DB.pm>. This file contains a reference to
787C<lib/MyApp/Schema.pm>, so that file is loaded next. Finally,
3533daff 788the call to C<load_classes> in that file will load each of the
d0496197 789table-specific "results source" files from the C<lib/MyApp/Schema>
3533daff 790subdirectory. These three table-specific DBIC schema files will then be
791used to create three table-specific Catalyst models every time the
792application starts (you can see these three model files listed in
793the debug output generated when you launch the application).
794
795
796=head2 Updating the Generated DBIC Schema Files
797
798
799Let's manually add some relationship information to the auto-generated
d0496197 800schema files. First edit C<lib/MyApp/Schema/Books.pm> and
3533daff 801add the following text below the C<# You can replace this text...>
802comment:
803
804 #
805 # Set relationships:
806 #
807
808 # has_many():
809 # args:
810 # 1) Name of relationship, DBIC will create accessor with this name
811 # 2) Name of the model class referenced by this relationship
812 # 3) Column name in *foreign* table
d0496197 813 __PACKAGE__->has_many(book_authors => 'MyApp::Schema::BookAuthors', 'book_id');
3533daff 814
815 # many_to_many():
816 # args:
817 # 1) Name of relationship, DBIC will create accessor with this name
818 # 2) Name of has_many() relationship this many_to_many() is shortcut for
819 # 3) Name of belongs_to() relationship in model class of has_many() above
820 # You must already have the has_many() defined to use a many_to_many().
821 __PACKAGE__->many_to_many(authors => 'book_authors', 'author');
822
823
824B<Note:> Be careful to put this code I<above> the C<1;> at the end of the
825file. As with any Perl package, we need to end the last line with
826a statement that evaluates to C<true>. This is customarily done with
827C<1;> on a line by itself.
828
829This code defines both a C<has_many> and a C<many_to_many> relationship.
830The C<many_to_many> relationship is optional, but it makes it easier to
831map a book to its collection of authors. Without it, we would have to
832"walk" though the C<book_authors> table as in C<$book-E<gt>book_authors-
833E<gt>first-E<gt>author-E<gt>last_name> (we will see examples on how to
834use DBIC objects in your code soon, but note that because C<$book-
835E<gt>book_authors> can return multiple authors, we have to use C<first>
836to display a single author). C<many_to_many> allows us to use the
837shorter C<$book-E<gt>authors-E<gt>first-E<gt>last_name>. Note that you
838cannot define a C<many_to_many> relationship without also having the
839C<has_many> relationship in place.
840
d0496197 841Then edit C<lib/MyApp/Schema/Authors.pm> and add relationship
3533daff 842information as follows (again, be careful to put in above the C<1;> but
843below the C<# DO NOT MODIFY THIS OR ANYTHING ABOVE!> comment):
844
845 #
846 # Set relationships:
847 #
848
849 # has_many():
850 # args:
851 # 1) Name of relationship, DBIC will create accessor with this name
852 # 2) Name of the model class referenced by this relationship
853 # 3) Column name in *foreign* table
d0496197 854 __PACKAGE__->has_many(book_author => 'MyApp::Schema::BookAuthors', 'author_id');
3533daff 855
856 # many_to_many():
857 # args:
858 # 1) Name of relationship, DBIC will create accessor with this name
859 # 2) Name of has_many() relationship this many_to_many() is shortcut for
860 # 3) Name of belongs_to() relationship in model class of has_many() above
861 # You must already have the has_many() defined to use a many_to_many().
862 __PACKAGE__->many_to_many(books => 'book_author', 'book');
863
864Finally, do the same for the "join table,"
d0496197 865C<lib/MyApp/Schema/BookAuthors.pm>:
3533daff 866
867 #
868 # Set relationships:
869 #
870
871 # belongs_to():
872 # args:
873 # 1) Name of relationship, DBIC will create accessor with this name
874 # 2) Name of the model class referenced by this relationship
875 # 3) Column name in *this* table
d0496197 876 __PACKAGE__->belongs_to(book => 'MyApp::Schema::Books', 'book_id');
3533daff 877
878 # belongs_to():
879 # args:
880 # 1) Name of relationship, DBIC will create accessor with this name
881 # 2) Name of the model class referenced by this relationship
882 # 3) Column name in *this* table
d0496197 883 __PACKAGE__->belongs_to(author => 'MyApp::Schema::Authors', 'author_id');
3533daff 884
885
886=head1 RUN THE APPLICATION
887
888Run the Catalyst "demo server" script with the C<DBIC_TRACE> option
889(it might still be enabled from earlier in the tutorial, but here
890is an alternate way to specify the option just in case):
891
892 $ DBIC_TRACE=1 script/myapp_server.pl
893
894Make sure that the application loads correctly and that you see the
895three dynamically created model class (one for each of the
896table-specific schema classes we created).
897
898Then hit the URL L<http://localhost:3000/books/list> and be sure that
899the book list is displayed.
900
901
902=head1 RUNNING THE APPLICATION FROM THE COMMAND LINE
903
904In some situations, it can be useful to run your application and
905display a page without using a browser. Catalyst lets you do this
906using the C<scripts/myapp_test.pl> script. Just supply the URL you
907wish to display and it will run that request through the normal
908controller dispatch logic and use the appropriate view to render the
909output (obviously, complex pages may dump a lot of text to your
910terminal window). For example, if you type:
911
912 $ script/myapp_test.pl "/books/list"
913
914You should get the same text as if you visited
915L<http://localhost:3000/books/list> with the normal development server
916and asked your browser to view the page source.
917
918
919=head1 UPDATING THE VIEW
920
921Let's add a new column to our book list page that takes advantage of
922the relationship information we manually added to our schema files
923in the previous section. Edit C<root/src/books/list.tt2> add add the
924following code below the existing table cell that contains
925C<book.rating> (IOW, add a new table cell below the existing two
926C<td> cells):
927
928 <td>
929 [% # First initialize a TT variable to hold a list. Then use a TT FOREACH -%]
930 [% # loop in 'side effect notation' to load just the last names of the -%]
931 [% # authors into the list. Note that the 'push' TT vmethod does not -%]
932 [% # a value, so nothing will be printed here. But, if you have something -%]
933 [% # in TT that does return a method and you don't want it printed, you -%]
934 [% # can: 1) assign it to a bogus value, or 2) use the CALL keyword to -%]
935 [% # call it and discard the return value. -%]
936 [% tt_authors = [ ];
937 tt_authors.push(author.last_name) FOREACH author = book.authors %]
938 [% # Now use a TT 'virtual method' to display the author count in parens -%]
939 [% # Note the use of the TT filter "| html" to escape dangerous characters -%]
940 ([% tt_authors.size | html %])
941 [% # Use another TT vmethod to join & print the names & comma separators -%]
942 [% tt_authors.join(', ') | html %]
943 </td>
944
945Then hit C<Ctrl+R> in your browser (not that you don't need to reload
946the development server or use the C<-r> option when updating TT
947templates) and you should now the the number of authors each book and
948a comma-separated list of the author's last names.
949
950If you are still running the development server with C<DBIC_TRACE>
951enabled, you should also now see five more C<SELECT> statements in the
952debug output (one for each book as the authors are being retrieved by
953DBIC).
954
955Also note that we are using "| html", a type of TT filter, to escape
956characters such as E<lt> and E<gt> to &lt; and &gt; and avoid various
957types of dangerous hacks against your application. In a real
958application, you would probably want to put "| html" at the end of
959every field where a user has control over the information that can
960appear in that field (and can therefore inject markup or code if you
961don't "neutralize" those fields). In addition to "| html", Template
962Toolkit has a variety of other useful filters that can found in the
963documentation for L<Template::Filters|Template::Filters>.
964
965
966=head2 Using C<RenderView> for the Default View
967
968B<NOTE: The rest of this part of the tutorial is optional. You can
969skip to Part 4, L<Basic CRUD|Catalyst::Manual::Tutorial::BasicCRUD>,
970if you wish.>
971
972Once your controller logic has processed the request from a user, it
973forwards processing to your view in order to generate the appropriate
974response output. Catalyst uses
975L<Catalyst::Action::RenderView|Catalyst::Action::RenderView> by
976default to automatically performs this operation. If you look in
977C<lib/MyApp/Controller/Root.pm>, you should see the empty
978definition for the C<sub end> method:
979
980 sub end : ActionClass('RenderView') {}
981
982The following bullet points provide a quick overview of the
983C<RenderView> process:
984
985=over 4
986
987=item *
988
989C<Root.pm> is designed to hold application-wide logic.
990
991=item *
992
993At the end of a given user request, Catalyst will call the most specific
994C<end> method that's appropriate. For example, if the controller for a
995request has an C<end> method defined, it will be called. However, if
996the controller does not define a controller-specific C<end> method, the
997"global" C<end> method in C<Root.pm> will be called.
998
999=item *
1000
1001Because the definition includes an C<ActionClass> attribute, the
1002L<Catalyst::Action::RenderView|Catalyst::Action::RenderView> logic
1003will be executed B<after> any code inside the definition of C<sub end>
1004is run. See L<Catalyst::Manual::Actions|Catalyst::Manual::Actions>
1005for more information on C<ActionClass>.
1006
1007=item *
1008
1009Because C<sub end> is empty, this effectively just runs the default
1010logic in C<RenderView>. However, you can easily extend the
1011C<RenderView> logic by adding your own code inside the empty method body
1012(C<{}>) created by the Catalyst Helpers when we first ran the
1013C<catalyst.pl> to initialize our application. See
1014L<Catalyst::Action::RenderView|Catalyst::Action::RenderView> for more
1015detailed information on how to extended C<RenderView> in C<sub end>.
1016
1017=back
1018
1019
1020=head2 Using The Default Template Name
1021
1022By default, C<Catalyst::View::TT> will look for a template that uses the
1023same name as your controller action, allowing you to save the step of
1024manually specifying the template name in each action. For example, this
1025would allow us to remove the
1026C<$c-E<gt>stash-E<gt>{template} = 'books/list.tt2';> line of our
1027C<list> action in the Books controller. Open
1028C<lib/MyApp/Controller/Books.pm> in your editor and comment out this line
1029to match the following (only the C<$c-E<gt>stash-E<gt>{template}> line
1030has changed):
1031
1032 =head2 list
1033
1034 Fetch all book objects and pass to books/list.tt2 in stash to be displayed
1035
1036 =cut
1037
1038 sub list : Local {
1039 # Retrieve the usual Perl OO '$self' for this object. $c is the Catalyst
1040 # 'Context' that's used to 'glue together' the various components
1041 # that make up the application
1042 my ($self, $c) = @_;
1043
1044 # Retrieve all of the book records as book model objects and store in the
1045 # stash where they can be accessed by the TT template
d0496197 1046 $c->stash->{books} = [$c->model('DB::Books')->all];
3533daff 1047
1048 # Set the TT template to use. You will almost always want to do this
1049 # in your action methods (actions methods respond to user input in
1050 # your controllers).
1051 #$c->stash->{template} = 'books/list.tt2';
1052 }
1053
1054C<Catalyst::View::TT> defaults to looking for a template with no
1055extension. In our case, we need to override this to look for an
1056extension of C<.tt2>. Open C<lib/MyApp/View/TT.pm> and add the
1057C<TEMPLATE_EXTENSION> definition as follows:
1058
1059 __PACKAGE__->config({
1060 CATALYST_VAR => 'Catalyst',
1061 INCLUDE_PATH => [
1062 MyApp->path_to( 'root', 'src' ),
1063 MyApp->path_to( 'root', 'lib' )
1064 ],
1065 PRE_PROCESS => 'config/main',
1066 WRAPPER => 'site/wrapper',
1067 ERROR => 'error.tt2',
1068 TIMER => 0,
1069 TEMPLATE_EXTENSION => '.tt2',
1070 });
1071
1072You should now be able to restart the development server as per the
1073previous section and access the L<http://localhost:3000/books/list>
1074as before.
1075
1076B<NOTE:> Please note that if you use the default template technique,
1077you will B<not> be able to use either the C<$c-E<gt>forward> or
1078the C<$c-E<gt>detach> mechanisms (these are discussed in Part 2 and
1079Part 9 of the Tutorial).
1080
1081
1082=head2 Return To A Manually-Specified Template
1083
1084In order to be able to use C<$c-E<gt>forward> and C<$c-E<gt>detach>
1085later in the tutorial, you should remove the comment from the
1086statement in C<sub list> in C<lib/MyApp/Controller/Books.pm>:
1087
1088 $c->stash->{template} = 'books/list.tt2';
1089
1090Then delete the C<TEMPLATE_EXTENSION> line in
1091C<lib/MyApp/View/TT.pm>.
1092
1093You should then be able to restart the development server and
1094access L<http://localhost:3000/books/list> in the same manner as
1095with earlier sections.
1096
1097
1098=head1 AUTHOR
1099
1100Kennedy Clark, C<hkclark@gmail.com>
1101
1102Please report any errors, issues or suggestions to the author. The
1103most recent version of the Catalyst Tutorial can be found at
1104L<http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst-Manual/lib/Catalyst/Manual/Tutorial/>.
1105
45c7830f 1106Copyright 2006-2008, Kennedy Clark, under Creative Commons License
3533daff 1107(L<http://creativecommons.org/licenses/by-nc-sa/2.5/>).
1108