fixed cookie-param list POD in C::Res
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Manual / Tutorial / CatalystBasics.pod
CommitLineData
4d583dd8 1=head1 NAME
2
64ccd8a8 3Catalyst::Manual::Tutorial::CatalystBasics - Catalyst Tutorial - Part 2: Catalyst Application Development Basics
4d583dd8 4
5
4d583dd8 6=head1 OVERVIEW
7
8This is B<Part 2 of 9> for the Catalyst tutorial.
9
64ccd8a8 10L<Tutorial Overview|Catalyst::Manual::Tutorial>
4d583dd8 11
12=over 4
13
14=item 1
15
16L<Introduction|Catalyst::Manual::Tutorial::Intro>
17
18=item 2
19
20B<Catalyst Basics>
21
22=item 3
23
653f4595 24L<Basic CRUD|Catalyst::Manual::Tutorial::BasicCRUD>
4d583dd8 25
26=item 4
27
28L<Authentication|Catalyst::Manual::Tutorial::Authentication>
29
30=item 5
31
32L<Authorization|Catalyst::Manual::Tutorial::Authorization>
33
34=item 6
35
36L<Debugging|Catalyst::Manual::Tutorial::Debugging>
37
38=item 7
39
40L<Testing|Catalyst::Manual::Tutorial::Testing>
41
42=item 8
43
653f4595 44L<Advanced CRUD|Catalyst::Manual::Tutorial::AdvancedCRUD>
4d583dd8 45
46=item 9
47
7d310f12 48L<Appendices|Catalyst::Manual::Tutorial::Appendices>
4d583dd8 49
50=back
51
208513f1 52
4d583dd8 53=head1 DESCRIPTION
54
64ccd8a8 55In this part of the tutorial, we will create a very basic Catalyst web
56application. Though simple in many respects, this section will already
57demonstrate a number of powerful capabilities such as:
4d583dd8 58
59=over 4
60
61=item * Helper Scripts
62
64ccd8a8 63Catalyst helper scripts that can be used to rapidly bootstrap the
64skeletal structure of an application.
4d583dd8 65
66=item * MVC
67
64ccd8a8 68Model/View/Controller (MVC) provides an architecture that facilitates a
69clean "separation of control" between the different portions of your
653f4595 70application. Given that many other documents cover this subject in
64ccd8a8 71detail, MVC will not be discussed in depth here (for an excellent
72introduction to MVC and general Catalyst concepts, please see
653f4595 73L<Catalyst::Manual::About>. In short:
4d583dd8 74
75=over 4
76
77=item * Model
78
653f4595 79The model usually represents a data store. In most applications, the
80model equates to the objects that are created from and saved to your SQL
81database.
4d583dd8 82
83=item * View
84
64ccd8a8 85The view takes model objects and renders them into something for the end
653f4595 86user to look at. Normally this involves a template-generation tool that
64ccd8a8 87creates HTML for the user's web browser, but it could easily be code
653f4595 88that generates other forms such as PDF documents, e-mails, or Excel
89spreadsheets.
4d583dd8 90
91=item * Controller
92
64ccd8a8 93As suggested by its name, the controller takes user requests and routes
94them to the necessary model and view.
4d583dd8 95
96=back
97
98=item * ORM
99
653f4595 100The use of Object-Relational Mapping (ORM) technology for database
101access. Specifically, ORM provides an automated and standardized means
102to persist and restore objects to/from a relational database.
4d583dd8 103
104=back
105
64ccd8a8 106B<TIP>: Note that all of the code for this part of the tutorial can be
107pulled from the Catalyst Subversion repository in one step with the
108following command:
4d583dd8 109
7d310f12 110 svn co http://dev.catalyst.perl.org/repos/Catalyst/tags/examples/Tutorial/MyApp/5.7/CatalystBasics MyApp
4d583dd8 111
112
4d583dd8 113=head1 CREATE A CATALYST PROJECT
114
64ccd8a8 115Catalyst provides a number of helper scripts that can be used to quickly
653f4595 116flesh out the basic structure of your application. All Catalyst projects
8112f931 117begin with the C<catalyst.pl> helper (see L<Catalyst::Helper|Catalyst::Helper>
118for more information on helpers). Also note that as of Catalyst 5.7000,
119you will not have the helper scripts unless you install both
120L<Catalyst::Runtime|Catalyst::Runtime> and L<Catalyst::Devel|Catalyst::Devel>.
4d583dd8 121
64ccd8a8 122In the case of this tutorial, use the Catalyst C<catalyst.pl> script to
123initialize the framework for an application called C<MyApp>:
4d583dd8 124
125 $ catalyst.pl MyApp
208513f1 126 created "MyApp"
127 created "MyApp/script"
128 created "MyApp/lib"
129 created "MyApp/root"
130 ...
131 created "MyApp/script/myapp_create.pl"
4d583dd8 132 $ cd MyApp
133
64ccd8a8 134The C<catalyst.pl> helper script will display the names of the
135directories and files it creates.
4d583dd8 136
653f4595 137Though it's too early for any significant celebration, we already have a
138functioning application. Run the following command to run this
139application with the built-in development web server:
4d583dd8 140
208513f1 141 $ script/myapp_server.pl
142 [debug] Debug messages enabled
143 [debug] Loaded plugins:
144 .----------------------------------------------------------------------------.
145 | Catalyst::Plugin::ConfigLoader 0.06 |
146 | Catalyst::Plugin::Static::Simple 0.14 |
147 '----------------------------------------------------------------------------'
148
149 [debug] Loaded dispatcher "Catalyst::Dispatcher"
150 [debug] Loaded engine "Catalyst::Engine::HTTP"
151 [debug] Found home "/root/dev/MyApp"
152 [debug] Loaded components:
153 .-----------------------------------------------------------------+----------.
154 | Class | Type |
155 +-----------------------------------------------------------------+----------+
156 | MyApp::Controller::Root | instance |
157 '-----------------------------------------------------------------+----------'
158
159 [debug] Loaded Private actions:
160 .----------------------+--------------------------------------+--------------.
161 | Private | Class | Method |
162 +----------------------+--------------------------------------+--------------+
163 | /default | MyApp::Controller::Root | default |
164 | /end | MyApp::Controller::Root | end |
165 '----------------------+--------------------------------------+--------------'
166
8e956464 167 [info] MyApp powered by Catalyst 5.7000
208513f1 168 You can connect to your server at http://localhost.localdomain:3000
169
f5ca9e89 170B<NOTE>: Be sure you run the C<script/myapp_server.pl> command from the
171'base' directory of your application, not inside the C<script> directory
172itself. It doesn't make a difference at this point, but it will as soon
173as we get the database going in the next section.
174
208513f1 175Point your web browser to L<http://localhost:3000> (substituting a
176different hostname or IP address as appropriate) and you should be
177greeted by the Catalyst welcome screen. Information similar to the
178following should be appended to the logging output of the development
179server:
180
7d310f12 181 [info] *** Request 1 (0.043/s) [6003] [Fri Jul 7 13:32:53 2006] ***
208513f1 182 [debug] "GET" request for "/" from "127.0.0.1"
7d310f12 183 [info] Request took 0.067675s (14.777/s)
208513f1 184 .----------------------------------------------------------------+-----------.
185 | Action | Time |
186 +----------------------------------------------------------------+-----------+
7d310f12 187 | /default | 0.002844s |
188 | /end | 0.000207s |
208513f1 189 '----------------------------------------------------------------+-----------'
190
191Press Ctrl-C to break out of the development server.
4d583dd8 192
4d583dd8 193
4d583dd8 194=head1 CREATE A SQLITE DATABASE
195
64ccd8a8 196In this step, we make a text file with the required SQL commands to
197create a database table and load some sample data. Open C<myapp01.sql>
198in your editor and enter:
4d583dd8 199
200 --
201 -- Create a very simple database to hold book and author information
202 --
203 CREATE TABLE books (
204 id INTEGER PRIMARY KEY,
205 title TEXT ,
206 rating INTEGER
207 );
208 -- 'book_authors' is a many-to-many join table between books & authors
209 CREATE TABLE book_authors (
210 book_id INTEGER,
211 author_id INTEGER,
212 PRIMARY KEY (book_id, author_id)
213 );
214 CREATE TABLE authors (
215 id INTEGER PRIMARY KEY,
216 first_name TEXT,
217 last_name TEXT
218 );
219 ---
220 --- Load some sample data
221 ---
222 INSERT INTO books VALUES (1, 'CCSP SNRS Exam Certification Guide', 5);
223 INSERT INTO books VALUES (2, 'TCP/IP Illustrated, Volume 1', 5);
224 INSERT INTO books VALUES (3, 'Internetworking with TCP/IP Vol.1', 4);
225 INSERT INTO books VALUES (4, 'Perl Cookbook', 5);
226 INSERT INTO books VALUES (5, 'Designing with Web Standards', 5);
227 INSERT INTO authors VALUES (1, 'Greg', 'Bastien');
228 INSERT INTO authors VALUES (2, 'Sara', 'Nasseh');
229 INSERT INTO authors VALUES (3, 'Christian', 'Degu');
230 INSERT INTO authors VALUES (4, 'Richard', 'Stevens');
231 INSERT INTO authors VALUES (5, 'Douglas', 'Comer');
232 INSERT INTO authors VALUES (6, 'Tom', 'Christiansen');
233 INSERT INTO authors VALUES (7, ' Nathan', 'Torkington');
234 INSERT INTO authors VALUES (8, 'Jeffrey', 'Zeldman');
235 INSERT INTO book_authors VALUES (1, 1);
236 INSERT INTO book_authors VALUES (1, 2);
237 INSERT INTO book_authors VALUES (1, 3);
238 INSERT INTO book_authors VALUES (2, 4);
239 INSERT INTO book_authors VALUES (3, 5);
240 INSERT INTO book_authors VALUES (4, 6);
241 INSERT INTO book_authors VALUES (4, 7);
242 INSERT INTO book_authors VALUES (5, 8);
243
64ccd8a8 244B<TIP>: See Appendix 1 for tips on removing the leading spaces when
c608fae5 245cutting and pasting example code from POD-based documents.
4d583dd8 246
247Then use the following command to build a C<myapp.db> SQLite database:
248
249 $ sqlite3 myapp.db < myapp01.sql
250
64ccd8a8 251If you need to create the database more than once, you probably want to
252issue the C<rm myapp.db> command to delete the database before you use
253the C<sqlite3 myapp.db < myapp01.sql> command.
4d583dd8 254
64ccd8a8 255Once the C<myapp.db> database file has been created and initialized, you
256can use the SQLite command line environment to do a quick dump of the
257database contents:
4d583dd8 258
259 $ sqlite3 myapp.db
260 SQLite version 3.2.2
261 Enter ".help" for instructions
262 sqlite> select * from books;
263 1|CCSP SNRS Exam Certification Guide|5
264 2|TCP/IP Illustrated, Volume 1|5
265 3|Internetworking with TCP/IP Vol.1|4
266 4|Perl Cookbook|5
267 5|Designing with Web Standards|5
268 sqlite> .q
269 $
270
271Or:
272
273 $ sqlite3 myapp.db "select * from books"
274 1|CCSP SNRS Exam Certification Guide|5
275 2|TCP/IP Illustrated, Volume 1|5
276 3|Internetworking with TCP/IP Vol.1|4
277 4|Perl Cookbook|5
278 5|Designing with Web Standards|5
279
64ccd8a8 280As with most other SQL tools, if you are using the full "interactive"
281environment you need to terminate your SQL commands with a ";" (it's not
282required if you do a single SQL statement on the command line). Use
283".q" to exit from SQLite from the SQLite interactive mode and return to
284your OS command prompt.
4d583dd8 285
286
4d583dd8 287=head1 EDIT THE LIST OF CATALYST PLUGINS
288
64ccd8a8 289One of the greatest benefits of Catalyst is that it has such a large
290library of plugins available. Plugins are used to seamlessly integrate
291existing Perl modules into the overall Catalyst framework. In general,
292they do this by adding additional methods to the C<context> object
293(generally written as C<$c>) that Catalyst passes to every component
294throughout the framework.
4d583dd8 295
296By default, Catalyst enables three plugins/flags:
297
298=over 4
299
300=item *
301
302C<-Debug> Flag
303
64ccd8a8 304Enables the Catalyst debug output you saw when we started the
305C<script/myapp_server.pl> development server earlier. You can remove
306this plugin when you place your application into production.
4d583dd8 307
64ccd8a8 308As you may have noticed, C<-Debug> is not a plugin, but a I<flag>.
309Although most of the items specified on the C<use Catalyst> line of your
310application class will be plugins, Catalyst supports a limited number of
14e6feb0 311flag options (of these, C<-Debug> is the most common). See the
312documentation for C<Catalyst.pm> to get details on other flags
313(currently C<-Engine>, C<-Home>, and C<-Log>).
4d583dd8 314
64ccd8a8 315If you prefer, you can use the C<$c-E<gt>debug> method to enable debug
316messages.
4d583dd8 317
318=item *
319
320L<Catalyst::Plugin::ConfigLoader|Catalyst::Plugin::ConfigLoader>
321
653f4595 322C<ConfigLoader> provides an automatic way to load configurable
64ccd8a8 323parameters for your application from a central YAML file (versus having
324the values hard-coded inside your Perl modules). If you have not been
325exposed to YAML before, it is a human-readable data serialization format
326that can be used to read (and write) values to/from text files. We will
327see how to use this feature of Catalyst during the authentication and
328authorization sections (Part 4 and Part 5).
4d583dd8 329
4d583dd8 330=item *
331
14e6feb0 332L<Catalyst::Plugin::Static::Simple|Catalyst::Plugin::Static::Simple>
4d583dd8 333
64ccd8a8 334C<Static::Simple> provides an easy method of serving static content such
335as images and CSS files under the development server.
4d583dd8 336
337=back
338
64ccd8a8 339To modify the list of plugins, edit C<lib/MyApp.pm> (this file is
340generally referred to as your I<application class>) and delete the line
341with:
4d583dd8 342
343 use Catalyst qw/-Debug ConfigLoader Static::Simple/;
344
345Replace it with:
346
347 use Catalyst qw/
348 -Debug
349 ConfigLoader
350 Static::Simple
351
4d583dd8 352 StackTrace
4d583dd8 353 /;
354
c608fae5 355This tells Catalyst to start using one new plugin:
4d583dd8 356
357=over 4
358
359=item *
360
4d583dd8 361L<Catalyst::Plugin::StackTrace|Catalyst::Plugin::StackTrace>
362
64ccd8a8 363Adds a stack trace to the standard Catalyst "debug screen" (this is the
364screen Catalyst sends to your browser when an error occurs).
4d583dd8 365
c19d127e 366Note: L<StackTrace|Catalyst::Plugin::StackTrace> output appears in your
367browser, not in the console window from which you're running your
368application, which is where logging output usually goes.
4d583dd8 369
4d583dd8 370=back
371
64ccd8a8 372Note that when specifying plugins on the C<use Catalyst> line, you can
71dedf57 373omit C<Catalyst::Plugin::> from the name. Additionally, you can spread
64ccd8a8 374the plugin names across multiple lines as shown here, or place them all
375on one (or more) lines as with the default configuration.
4d583dd8 376
c608fae5 377B<TIP:> You may see examples that include the
378L<Catalyst::Plugin::DefaultEnd|Catalyst::Plugin::DefaultEnd>
8e956464 379plugins. As of Catalyst 5.7000, C<DefaultEnd> has been
c608fae5 380deprecated in favor of
381L<Catalyst::Action::RenderView|Catalyst::Action::RenderView>
382(as the name of the package suggests, C<RenderView> is not
383a plugin, but an action). The purpose of both is essentially the same:
208513f1 384forward processing to the view to be rendered. Applications generated
8e956464 385under 5.7000 should automatically use C<RenderView> and "just work"
208513f1 386for most applications. For more information on C<RenderView> and
387the various options for forwarding to your view logic, please refer
388to the "Using RenderView for the Default View" section under
389"CATALYST VIEWS" below.
c608fae5 390
391
4d583dd8 392=head1 DATABASE ACCESS WITH C<DBIx::Class>
393
64ccd8a8 394Catalyst can be used with virtually any form of persistent datastore
14e6feb0 395available via Perl. For example,
396L<Catalyst::Model::DBI|Catalyst::Model::DBI> can be used to
397easily access databases through the traditional Perl C<DBI> interface.
71dedf57 398However, most Catalyst applications use some form of ORM technology to
64ccd8a8 399automatically create and save model objects as they are used. Although
14e6feb0 400Tony Bowden's L<Class::DBI|Class::DBI> has been the traditional
401Perl ORM engine, Matt Trout's L<DBIx::Class|DBIx::Class> (abbreviated
402as "DBIC") has rapidly emerged as the Perl-based ORM technology of choice.
403Most new Catalyst applications rely on DBIC, as will this tutorial.
4d583dd8 404
14e6feb0 405Note: See L<Catalyst:: Model::CDBI> for more information on using
406Catalyst with L<Class::DBI|Class::DBI>.
4d583dd8 407
408=head2 Create a DBIC Schema File
409
64ccd8a8 410DBIx::Class uses a schema file to load other classes that represent the
411tables in your database (DBIC refers to these "table objects" as "result
71dedf57 412sources"; see L<DBIx::Class::ResultSource>). In this case, we want to
413load the model object for the C<books>, C<book_authors>, and C<authors>
414tables created in the previous step.
4d583dd8 415
416Open C<lib/MyAppDB.pm> in your editor and insert:
417
418 package MyAppDB;
419
420 =head1 NAME
421
71dedf57 422 MyAppDB - DBIC Schema Class
4d583dd8 423
424 =cut
425
426 # Our schema needs to inherit from 'DBIx::Class::Schema'
427 use base qw/DBIx::Class::Schema/;
428
429 # Need to load the DB Model classes here.
430 # You can use this syntax if you want:
431 # __PACKAGE__->load_classes(qw/Book BookAuthor Author/);
432 # Also, if you simply want to load all of the classes in a directory
433 # of the same name as your schema class (as we do here) you can use:
434 # __PACKAGE__->load_classes(qw//);
435 # But the variation below is more flexible in that it can be used to
436 # load from multiple namespaces.
437 __PACKAGE__->load_classes({
438 MyAppDB => [qw/Book BookAuthor Author/]
439 });
440
441 1;
442
64ccd8a8 443B<Note:> C<__PACKAGE__> is just a shorthand way of referencing the name
444of the package where it is used. Therefore, in C<MyAppDB.pm>,
14e6feb0 445C<__PACKAGE__> is equivalent to C<MyAppDB>.
4d583dd8 446
447
448=head2 Create the DBIC "Result Source" Files
449
64ccd8a8 450In this step, we create "table classes" (again, these are called a
71dedf57 451"result source" classes in DBIC) that act as model objects for the
64ccd8a8 452C<books>, C<book_authors>, and C<authors> tables in our database.
4d583dd8 453
454First, create a directory to hold the class:
455
456 $ mkdir lib/MyAppDB
457
458Then open C<lib/MyAppDB/Book.pm> in your editor and enter:
459
460 package MyAppDB::Book;
461
462 use base qw/DBIx::Class/;
463
464 # Load required DBIC stuff
465 __PACKAGE__->load_components(qw/PK::Auto Core/);
466 # Set the table name
467 __PACKAGE__->table('books');
468 # Set columns in table
469 __PACKAGE__->add_columns(qw/id title rating/);
470 # Set the primary key for the table
471 __PACKAGE__->set_primary_key(qw/id/);
472
473 #
474 # Set relationships:
475 #
476
477 # has_many():
478 # args:
479 # 1) Name of relationship, DBIC will create accessor with this name
480 # 2) Name of the model class referenced by this relationship
481 # 3) Column name in *foreign* table
482 __PACKAGE__->has_many(book_authors => 'MyAppDB::BookAuthor', 'book_id');
483
484 # many_to_many():
485 # args:
486 # 1) Name of relationship, DBIC will create accessor with this name
487 # 2) Name of has_many() relationship this many_to_many() is shortcut for
488 # 3) Name of belongs_to() relationship in model class of has_many() above
489 # You must already have the has_many() defined to use a many_to_many().
490 __PACKAGE__->many_to_many(authors => 'book_authors', 'author');
491
492
493 =head1 NAME
494
495 MyAppDB::Book - A model object representing a book.
496
497 =head1 DESCRIPTION
498
499 This is an object that represents a row in the 'books' table of your application
500 database. It uses DBIx::Class (aka, DBIC) to do ORM.
501
502 For Catalyst, this is designed to be used through MyApp::Model::MyAppDB.
503 Offline utilities may wish to use this class directly.
504
505 =cut
506
507 1;
508
64ccd8a8 509This defines both a C<has_many> and a C<many_to_many> relationship. The
510C<many_to_many> relationship is optional, but it makes it easier to map
511a book to its collection of authors. Without it, we would have to
512"walk" though the C<book_authors> table as in
513C<$book-E<gt>book_authors-E<gt>first-E<gt>author-E<gt>last_name> (we
514will see examples on how to use DBIC objects in your code soon, but note
515that because C<$book-E<gt>book_authors> can return multiple authors, we
71dedf57 516have to use C<first> to display a single author). C<many_to_many> allows
517us to use the shorter C<$book-E<gt>authors-E<gt>first-E<gt>last_name>.
518Note that you cannot define a C<many_to_many> relationship without also
519having the C<has_many> relationship in place.
4d583dd8 520
521Next, open C<lib/MyAppDB/Author.pm> in your editor and enter:
522
523 package MyAppDB::Author;
524
525 use base qw/DBIx::Class/;
526
527 # Load required DBIC stuff
528 __PACKAGE__->load_components(qw/PK::Auto Core/);
529 # Set the table name
530 __PACKAGE__->table('authors');
531 # Set columns in table
532 __PACKAGE__->add_columns(qw/id first_name last_name/);
533 # Set the primary key for the table
534 __PACKAGE__->set_primary_key(qw/id/);
208513f1 535
4d583dd8 536 #
537 # Set relationships:
538 #
539
540 # has_many():
541 # args:
542 # 1) Name of relationship, DBIC will create accessor with this name
543 # 2) Name of the model class referenced by this relationship
544 # 3) Column name in *foreign* table
545 __PACKAGE__->has_many(book_author => 'MyAppDB::BookAuthor', 'author_id');
546
547 # many_to_many():
548 # args:
549 # 1) Name of relationship, DBIC will create accessor with this name
550 # 2) Name of has_many() relationship this many_to_many() is shortcut for
551 # 3) Name of belongs_to() relationship in model class of has_many() above
552 # You must already have the has_many() defined to use a many_to_many().
553 __PACKAGE__->many_to_many(books => 'book_author', 'book');
554
555
556 =head1 NAME
557
558 MyAppDB::Author - A model object representing an author of a book (if a book has
559 multiple authors, each will be represented be separate Author object).
560
561 =head1 DESCRIPTION
562
563 This is an object that represents a row in the 'authors' table of your application
564 database. It uses DBIx::Class (aka, DBIC) to do ORM.
565
566 For Catalyst, this is designed to be used through MyApp::Model::MyAppDB.
567 Offline utilities may wish to use this class directly.
568
569 =cut
570
571 1;
572
573Finally, open C<lib/MyAppDB/BookAuthor.pm> in your editor and enter:
574
575 package MyAppDB::BookAuthor;
576
577 use base qw/DBIx::Class/;
578
579 # Load required DBIC stuff
580 __PACKAGE__->load_components(qw/PK::Auto Core/);
581 # Set the table name
582 __PACKAGE__->table('book_authors');
583 # Set columns in table
584 __PACKAGE__->add_columns(qw/book_id author_id/);
585 # Set the primary key for the table
586 __PACKAGE__->set_primary_key(qw/book_id author_id/);
587
588 #
589 # Set relationships:
590 #
591
592 # belongs_to():
593 # args:
594 # 1) Name of relationship, DBIC will create accessor with this name
595 # 2) Name of the model class referenced by this relationship
596 # 3) Column name in *this* table
597 __PACKAGE__->belongs_to(book => 'MyAppDB::Book', 'book_id');
208513f1 598
4d583dd8 599 # belongs_to():
600 # args:
601 # 1) Name of relationship, DBIC will create accessor with this name
602 # 2) Name of the model class referenced by this relationship
603 # 3) Column name in *this* table
604 __PACKAGE__->belongs_to(author => 'MyAppDB::Author', 'author_id');
605
606
607 =head1 NAME
608
609 MyAppDB::BookAuthor - A model object representing the JOIN between an author and
610 a book.
611
612 =head1 DESCRIPTION
613
614 This is an object that represents a row in the 'book_authors' table of your
615 application database. It uses DBIx::Class (aka, DBIC) to do ORM.
208513f1 616
4d583dd8 617 You probably won't need to use this class directly -- it will be automatically
618 used by DBIC where joins are needed.
619
620 For Catalyst, this is designed to be used through MyApp::Model::MyAppDB.
621 Offline utilities may wish to use this class directly.
622
623 =cut
624
625 1;
626
64ccd8a8 627B<Note:> This sample application uses a plural form for the database
628tables (e.g., C<books> and C<authors>) and a singular form for the model
629objects (e.g., C<Book> and C<Author>); however, Catalyst places no
630restrictions on the naming conventions you wish to use.
4d583dd8 631
4d583dd8 632=head2 Use C<Catalyst::Model::DBIC::Schema> To Load The Model Class
633
14e6feb0 634When L<Catalyst::Model::DBIC::Schema|Catalyst::Model::DBIC::Schema> is
64ccd8a8 635in use, Catalyst essentially reads an existing copy of your database
636model and creates a new set of objects under C<MyApp::Model> for use
637inside of Catalyst.
4d583dd8 638
14e6feb0 639B<Note:> With
640L<Catalyst::Model::DBIC::Schema|Catalyst::Model::DBIC::Schema> you
641essentially end up with two sets of model classes (only one of which
642you write... the other set is created automatically in memory when
643your Catalyst application initializes). For this tutorial application,
644the important points to remember are: you write the I<result source>
645files in C<MyAppDB>, but I<within Catalyst> you use the I<automatically
646created model classes> in C<MyApp::Model>.
4d583dd8 647
14e6feb0 648Use the
649L<Catalyst::Helper::Model::DBIC::Schema|Catalyst::Helper::Model::DBIC::Schema>
650helper script to create the model class that loads up the model we
651created in the previous step:
4d583dd8 652
653 $ script/myapp_create.pl model MyAppDB DBIC::Schema MyAppDB dbi:SQLite:myapp.db '' '' '{ AutoCommit => 1 }'
208513f1 654 exists "/root/dev/MyApp/script/../lib/MyApp/Model"
655 exists "/root/dev/MyApp/script/../t"
656 created "/root/dev/MyApp/script/../lib/MyApp/Model/MyAppDB.pm"
657 created "/root/dev/MyApp/script/../t/model_MyAppDB.t"
658
4d583dd8 659
64ccd8a8 660Where the first C<MyAppDB> is the name of the class to be created by the
661helper in C<lib/MyApp/Model> and the second C<MyAppDB> is the name of
662existing schema file we created (in C<lib/MyAppDB.pm>). You can see
663that the helper creates a model file under C<lib/MyApp/Model> (Catalyst
664has a separate directory under C<lib/MyApp> for each of the three parts
665of MVC: C<Model>, C<View>, and C<Controller> [although older Catalyst
666applications often use the directories C<M>, C<V>, and C<C>]).
4d583dd8 667
668
4d583dd8 669=head1 CREATE A CATALYST CONTROLLER
670
71dedf57 671Controllers are where you write methods that interact with user
672input--typically, controller methods respond to C<GET> and C<POST>
673messages from the user's web browser.
4d583dd8 674
71dedf57 675Use the Catalyst C<create> script to add a controller for book-related
676actions:
4d583dd8 677
678 $ script/myapp_create.pl controller Books
208513f1 679 exists "/root/dev/MyApp/script/../lib/MyApp/Controller"
680 exists "/root/dev/MyApp/script/../t"
681 created "/root/dev/MyApp/script/../lib/MyApp/Controller/Books.pm"
682 created "/root/dev/MyApp/script/../t/controller_Books.t"
4d583dd8 683
64ccd8a8 684Then edit C<lib/MyApp/Controller/Books.pm> and add the following method
685to the controller:
4d583dd8 686
687 =head2 list
688
689 Fetch all book objects and pass to books/list.tt2 in stash to be displayed
690
691 =cut
692
693 sub list : Local {
694 # Retrieve the usual perl OO '$self' for this object. $c is the Catalyst
695 # 'Context' that's used to 'glue together' the various components
696 # that make up the application
697 my ($self, $c) = @_;
698
699 # Retrieve all of the book records as book model objects and store in the
700 # stash where they can be accessed by the TT template
701 $c->stash->{books} = [$c->model('MyAppDB::Book')->all];
702
703 # Set the TT template to use. You will almost always want to do this
8112f931 704 # in your action methods (actions methods respond to user input in
705 # your controllers).
4d583dd8 706 $c->stash->{template} = 'books/list.tt2';
707 }
708
64ccd8a8 709B<Note:> Programmers experienced with object-oriented Perl should
710recognize C<$self> as a reference to the object where this method was
711called. On the other hand, C<$c> will be new to many Perl programmers
712who have not used Catalyst before (it's sometimes written as
713C<$context>). The Context object is automatically passed to all
714Catalyst components. It is used to pass information between components
715and provide access to Catalyst and plugin functionality.
4d583dd8 716
64ccd8a8 717B<TIP>: You may see the C<$c-E<gt>model('MyAppDB::Book')> used above
718written as C<$c-E<gt>model('MyAppDB')-E<gt>resultset('Book)>. The two
719are equivalent.
4d583dd8 720
64ccd8a8 721B<Note:> Catalyst actions are regular Perl methods, but they make use of
14e6feb0 722Nicholas Clark's C<attributes> module (that's the C<: Local> next to the
723C<sub list> in the code above) to provide additional information to the
724Catalyst dispatcher logic.
4d583dd8 725
208513f1 726
4d583dd8 727=head1 CATALYST VIEWS
728
71dedf57 729Views are where you render output, typically for display in the user's
14e6feb0 730web browser, but also possibly using other display output-generation
71dedf57 731systems. As with virtually every aspect of Catalyst, options abound
732when it comes to the specific view technology you adopt inside your
733application. However, most Catalyst applications use the Template
734Toolkit, known as TT (for more information on TT, see
208513f1 735L<http://www.template-toolkit.org>). Other popular view technologies
71dedf57 736include Mason (L<http://www.masonhq.com> and
14e6feb0 737L<http://www.masonbook.com>) and L<HTML::Template|HTML::Template>
64ccd8a8 738(L<http://html-template.sourceforge.net>).
4d583dd8 739
70493af7 740=head2 Create a Catalyst View Using C<TTSite>
4d583dd8 741
742When using TT for the Catalyst view, there are two main helper scripts:
743
744=over 4
745
746=item *
747
14e6feb0 748L<Catalyst::Helper::View::TT|Catalyst::Helper::View::TT>
4d583dd8 749
750=item *
751
14e6feb0 752L<Catalyst::Helper::View::TTSite|Catalyst::Helper::View::TTSite>
4d583dd8 753
754=back
755
64ccd8a8 756Both are similar, but C<TT> merely creates the C<lib/MyApp/View/TT.pm>
757file and leaves the creation of any hierarchical template organization
71dedf57 758entirely up to you. (It also creates a C<t/view_TT.t> file for testing;
759test cases will be discussed in Part 7). The C<TTSite> helper creates a
760modular and hierarchical view layout with separate Template Toolkit (TT)
761files for common header and footer information, configuration values, a
762CSS stylesheet, and more.
4d583dd8 763
64ccd8a8 764Enter the following command to enable the C<TTSite> style of view
71dedf57 765rendering for this tutorial:
4d583dd8 766
767 $ script/myapp_create.pl view TT TTSite
208513f1 768 exists "/root/dev/MyApp/script/../lib/MyApp/View"
769 exists "/root/dev/MyApp/script/../t"
770 created "/root/dev/MyApp/script/../lib/MyApp/View/TT.pm"
771 created "/root/dev/MyApp/script/../root/lib"
772 ...
773 created "/root/dev/MyApp/script/../root/src/ttsite.css"
4d583dd8 774
64ccd8a8 775This puts a number of files in the C<root/lib> and C<root/src>
776directories that can be used to customize the look and feel of your
777application. Also take a look at C<lib/MyApp/View/TT.pm> for config
778values set by the C<TTSite> helper.
779
780B<TIP>: Note that TTSite does one thing that could confuse people who
208513f1 781are used to the normal C<TT> Catalyst view: it redefines the Catalyst
71dedf57 782context object in templates from its usual C<c> to C<Catalyst>. When
783looking at other Catalyst examples, remember that they almost always use
784C<c>. Note that Catalyst and TT I<do not complain> when you use the
785wrong name to access the context object...TT simply outputs blanks for
5c1f2a06 786that bogus logic (see next tip to change this behavior with TT C<DEBUG>
787options). Finally, be aware that this change in name I<only>
71dedf57 788applies to how the context object is accessed inside your TT templates;
64ccd8a8 789your controllers will continue to use C<$c> (or whatever name you use
71dedf57 790when fetching the reference from C<@_> inside your methods). (You can
64ccd8a8 791change back to the "default" behavior be removing the C<CATALYST_VAR>
792line from C<lib/MyApp/View/TT.pm>, but you will also have to edit
793C<root/lib/config/main> and C<root/lib/config/url>. If you do this, be
794careful not to have a collision between your own C<c> variable and the
795Catalyst C<c> variable.)
4d583dd8 796
5c1f2a06 797B<TIP>: When troubleshooting TT it can be helpful to enable variable
798C<DEBUG> options. You can do this in a Catalyst environment by adding
799a C<DEBUG> line to the C<__PACKAGE__->config> declaration in
8112f931 800C<lib/MyApp/View/TT.pm>:
5c1f2a06 801
802 __PACKAGE__->config({
803 CATALYST_VAR => 'Catalyst',
804 ...
805 DEBUG => 'undef',
806 ...
807 });
208513f1 808
5c1f2a06 809There are a variety of options you can use, such as 'undef', 'all',
810'service', 'context', 'parser', 'provider', and 'service'. See
811L<Template::Constants> for more information (remove the C<DEBUG_>
812portion of the name shown in the TT docs and convert to lower case
813for use inside Catalyst).
814
70493af7 815B<NOTE:> Please be sure to disable TT debug options before
816continuing the tutorial (especially the 'undef' option -- leaving
817this enabled will conflict with several of the conventions used
818by this tutorial and TTSite to leave some variables undefined
819on purpose).
820
5c1f2a06 821
208513f1 822=head2 Using C<RenderView> for the Default View
823
824Once your controller logic has processed the request from a user, it
825forwards processing to your view in order to generate the appropriate
8e956464 826response output. Catalyst v5.7000 ships with a new mechanism,
208513f1 827L<Catalyst::Action::RenderView|Catalyst::Action::RenderView>, that
828automatically performs this operation. If you look in
829C<lib/MyApp/Controller/Root.pm>, you should see the this empty
830definition for the C<sub end> method:
831
832 sub end : ActionClass('RenderView') {}
833
834The following bullet points provide a quick overview of the
835C<RenderView> process:
836
837=over 4
838
839=item *
840
841C<Root.pm> is designed to hold application-wide logic.
842
843=item *
844
845At the end of a given user request, Catalyst will call the most specific
846C<end> method that's appropriate. For example, if the controller for a
847request has an C<end> method defined, it will be called. However, if
848the controller does not define a controller-specific C<end> method, the
849"global" C<end> method in C<Root.pm> will be called.
c608fae5 850
208513f1 851=item *
852
853Because the definition includes an C<ActionClass> attribute, the
854L<Catalyst::Action::RenderView|Catalyst::Action::RenderView> logic
565d379b 855will be executed B<after> any code inside the definition of C<sub end>
208513f1 856is run. See L<Catalyst::Manual::Actions|Catalyst::Manual::Actions>
857for more information on C<ActionClass>.
858
859=item *
860
861Because C<sub end> is empty, this effectively just runs the default
862logic in C<RenderView>. However, you can easily extend the
863C<RenderView> logic by adding your own code inside the empty method body
864(C<{}>) created by the Catalyst Helpers when we first ran the
865C<catalyst.pl> to initialize our application. See
866L<Catalyst::Action::RenderView|Catalyst::Action::RenderView> for more
867detailed information on how to extended C<RenderView> in C<sub end>.
868
869=back
870
871
872=head3 The History Leading Up To C<RenderView>
873
874Although C<RenderView> strikes a nice balance between default
875behavior and easy extensibility, it is a new feature that won't
876appear in most existing Catalyst examples. This section provides
877some brief background on the evolution of default view rendering
878logic with an eye to how they can be migrated to C<RenderView>:
c608fae5 879
880=over 4
881
882=item *
883
884Private C<end> Action in Application Class
885
886Older Catalyst-related documents often suggest that you add a "private
887end action" to your application class (C<MyApp.pm>) or Root.pm
888(C<MyApp/Controller/Root.pm>). These examples should be easily
208513f1 889converted to L<RenderView|Catalyst::Action::RenderView> by simply adding
8112f931 890the attribute C<:ActionClass('RenderView')> to the C<sub end>
891definition. If end sub is defined in your application class
892(C<MyApp.pm>), you should also migrate it to
893C<MyApp/Controller/Root.pm>.
c608fae5 894
895=item *
896
897L<Catalyst::Plugin::DefaultEnd|Catalyst::Plugin::DefaultEnd>
898
208513f1 899C<DefaultEnd> represented the "next step" in passing processing from
900your controller to your view. It has the advantage of only requiring
901that C<DefaultEnd> be added to the list of plugins in C<lib/MyApp.pm>.
902It also allowed you to add "dump_info=1" (precede with "?" or "&"
903depending on where it is in the URL) to I<force> the debug screen at the
904end of the Catalyst request processing cycle. However, it was more
c9b77c06 905difficult to extend than the C<RenderView> mechanism, and is now
906deprecated.
c608fae5 907
908=item *
909
910L<Catalyst::Action::RenderView|Catalyst::Action::RenderView>
911
208513f1 912As discussed above, the current recommended approach to handling your
913view logic relies on
c608fae5 914L<Catalyst::Action::RenderView|Catalyst::Action::RenderView>. Although
208513f1 915similar in first appearance to the "private end action" approach, it
916utilizes Catalyst's "ActionClass" mechanism to provide both automatic
917default behavior (you don't have to include a plugin as with
918C<DefaultEnd>) and easy extensibility. As with C<DefaultEnd>, it allows
919you to add "dump_info=1" (precede with "?" or "&" depending on where it
920is in the URL) to I<force> the debug screen at the end of the Catalyst
921request processing cycle.
c608fae5 922
923=back
924
208513f1 925It is recommended that all Catalyst applications use or migrate to
926the C<RenderView> approach.
c608fae5 927
928
4d583dd8 929=head2 Globally Customize Every View
930
64ccd8a8 931When using TTSite, files in the subdirectories of C<root/lib> can be
932used to make changes that will appear in every view. For example, to
933display optional status and error messages in every view, edit
71dedf57 934C<root/lib/site/layout>, updating it to match the following (the two HTML
64ccd8a8 935C<span> elements are new):
4d583dd8 936
937 <div id="header">[% PROCESS site/header %]</div>
938
939 <div id="content">
940 <span class="message">[% status_msg %]</span>
941 <span class="error">[% error_msg %]</span>
942 [% content %]
943 </div>
944
945 <div id="footer">[% PROCESS site/footer %]</div>
946
64ccd8a8 947If we set either message in the Catalyst stash (e.g.,
71dedf57 948C<$c-E<gt>stash-E<gt>{status_msg} = 'Request was successful!'>) it will
949be displayed whenever any view used by that request is rendered. The
950C<message> and C<error> CSS styles are automatically defined in
951C<root/src/ttsite.css> and can be customized to suit your needs.
4d583dd8 952
64ccd8a8 953B<Note:> The Catalyst stash only lasts for a single HTTP request. If
954you need to retain information across requests you can use
14e6feb0 955L<Catalyst::Plugin::Session|Catalyst::Plugin::Session> (we will use
956Catalyst sessions in the Authentication part of the tutorial).
4d583dd8 957
958
959=head2 Create a TT Template Page
960
64ccd8a8 961To add a new page of content to the TTSite view hierarchy, just create a
962new C<.tt2> file in C<root/src>. Only include HTML markup that goes
963inside the HTML <body> and </body> tags, TTSite will use the contents of
964C<root/lib/site> to add the top and bottom.
4d583dd8 965
966First create a directory for book-related TT templates:
967
968 $ mkdir root/src/books
969
970Then open C<root/src/books/list.tt2> in your editor and enter:
971
972 [% # This is a TT comment. The '-' at the end "chomps" the newline. You won't -%]
973 [% # see this "chomping" in your browser because HTML ignores blank lines, but -%]
974 [% # it WILL eliminate a blank line if you view the HTML source. It's purely -%]
975 [%- # optional, but both the beginning and the ending TT tags support chomping. -%]
976
977 [% # Provide a title to root/lib/site/header -%]
978 [% META title = 'Book List' -%]
979
980 <table>
981 <tr><th>Title</th><th>Rating</th><th>Author(s)</th></tr>
982 [% # Display each book in a table row %]
983 [% FOREACH book IN books -%]
984 <tr>
985 <td>[% book.title %]</td>
986 <td>[% book.rating %]</td>
987 <td>
14e6feb0 988 [% # First initialize a TT variable to hold a list. Then use a TT FOREACH -%]
989 [% # loop in 'side effect notation' to load just the last names of the -%]
c9b77c06 990 [% # authors into the list. Note that the 'push' TT vmethod does not -%]
991 [% # a value, so nothing will be printed here. But, if you have something -%]
992 [% # in TT that does return a method and you don't want it printed, you -%]
993 [% # can: 1) assign it to a bogus value, or 2) use the CALL keyword to -%]
994 [% # call it and discard the return value. -%]
14e6feb0 995 [% tt_authors = [ ];
c9b77c06 996 tt_authors.push(author.last_name) FOREACH author = book.authors %]
14e6feb0 997 [% # Now use a TT 'virtual method' to display the author count in parens -%]
998 ([% tt_authors.size %])
c9b77c06 999 [% # Use another TT vmethod to join & print the names & comma separators -%]
14e6feb0 1000 [% tt_authors.join(', ') %]
4d583dd8 1001 </td>
1002 </tr>
1003 [% END -%]
1004 </table>
1005
64ccd8a8 1006As indicated by the inline comments above, the C<META title> line uses
1007TT's META feature to provide a title to C<root/lib/site/header>.
1008Meanwhile, the outer C<FOREACH> loop iterates through each C<book> model
1009object and prints the C<title> and C<rating> fields. An inner
14e6feb0 1010C<FOREACH> loop prints the last name of each author in a comma-separated
1011list within a single table cell.
64ccd8a8 1012
71dedf57 1013If you are new to TT, the C<[%> and C<%]> tags are used to delimit TT
1014code. TT supports a wide variety of directives for "calling" other
64ccd8a8 1015files, looping, conditional logic, etc. In general, TT simplifies the
1016usual range of Perl operators down to the single dot (C<.>) operator.
1017This applies to operations as diverse as method calls, hash lookups, and
1018list index values (see
1019L<http://www.template-toolkit.org/docs/default/Manual/Variables.html>
1020for details and examples). In addition to the usual C<Template> module
1021Pod documentation, you can access the TT manual at
1022L<http://www.template-toolkit.org/docs/default/>.
1023
1024B<NOTE>: The C<TTSite> helper creates several TT files using an
1025extension of C<.tt2>. Most other Catalyst and TT examples use an
1026extension of C<.tt>. You can use either extension (or no extension at
1027all) with TTSite and TT, just be sure to use the appropriate extension
1028for both the file itself I<and> the C<$c-E<gt>stash-E<gt>{template} =
1029...> line in your controller. This document will use C<.tt2> for
1030consistency with the files already created by the C<TTSite> helper.
4d583dd8 1031
1032
4d583dd8 1033=head1 RUN THE APPLICATION
1034
64ccd8a8 1035First, let's enable an environment variable option that causes
1036DBIx::Class to dump the SQL statements it's using to access the database
1037(this option can provide extremely helpful troubleshooting information):
4d583dd8 1038
1039 $ export DBIX_CLASS_STORAGE_DBI_DEBUG=1
1040
cc548726 1041This assumes you are using BASH as your shell -- adjust accordingly if
1042you are using a different shell (for example, under tcsh, use
1043C<setenv DBIX_CLASS_STORAGE_DBI_DEBUG 1>).
1044
64ccd8a8 1045B<NOTE>: You can also set this in your code using
1046C<$class-E<gt>storage-E<gt>debug(1);>. See
71dedf57 1047L<DBIx::Class::Manual::Troubleshooting> for details (including options
1048to log to file instead of displaying to the Catalyst development server
1049log).
4d583dd8 1050
1051Then run the Catalyst "demo server" script:
1052
1053 $ script/myapp_server.pl
1054
208513f1 1055Your development server log output should display something like:
4d583dd8 1056
1057 $ script/myapp_server.pl
208513f1 1058 [debug] Debug messages enabled
1059 [debug] Loaded plugins:
1060 .----------------------------------------------------------------------------.
1061 | Catalyst::Plugin::ConfigLoader 0.06 |
1062 | Catalyst::Plugin::StackTrace 0.04 |
1063 | Catalyst::Plugin::Static::Simple 0.14 |
1064 '----------------------------------------------------------------------------'
4d583dd8 1065
208513f1 1066 [debug] Loaded dispatcher "Catalyst::Dispatcher"
1067 [debug] Loaded engine "Catalyst::Engine::HTTP"
1068 [debug] Found home "/home/me/MyApp"
1069 [debug] Loaded components:
1070 .-----------------------------------------------------------------+----------.
1071 | Class | Type |
1072 +-----------------------------------------------------------------+----------+
1073 | MyApp::Controller::Books | instance |
1074 | MyApp::Controller::Root | instance |
1075 | MyApp::Model::MyAppDB | instance |
1076 | MyApp::Model::MyAppDB::Author | class |
1077 | MyApp::Model::MyAppDB::Book | class |
1078 | MyApp::Model::MyAppDB::BookAuthor | class |
1079 | MyApp::View::TT | instance |
1080 '-----------------------------------------------------------------+----------'
4d583dd8 1081
208513f1 1082 [debug] Loaded Private actions:
1083 .----------------------+--------------------------------------+--------------.
1084 | Private | Class | Method |
1085 +----------------------+--------------------------------------+--------------+
1086 | /default | MyApp::Controller::Root | default |
1087 | /end | MyApp::Controller::Root | end |
1088 | /books/index | MyApp::Controller::Books | index |
1089 | /books/list | MyApp::Controller::Books | list |
1090 '----------------------+--------------------------------------+--------------'
4d583dd8 1091
208513f1 1092 [debug] Loaded Path actions:
1093 .-------------------------------------+--------------------------------------.
1094 | Path | Private |
1095 +-------------------------------------+--------------------------------------+
1096 | /books/list | /books/list |
1097 '-------------------------------------+--------------------------------------'
4d583dd8 1098
8e956464 1099 [info] MyApp powered by Catalyst 5.7000
208513f1 1100 You can connect to your server at http://localhost.localdomain:3000
4d583dd8 1101
1102Some things you should note in the output above:
1103
1104=over 4
1105
1106=item *
1107
64ccd8a8 1108Catalyst::Model::DBIC::Schema took our C<MyAppDB::Book> and made it
1109C<MyApp::Model::MyAppDB::Book> (and similar actions were performed on
1110C<MyAppDB::Author> and C<MyAppDB::BookAuthor>).
4d583dd8 1111
1112=item *
1113
64ccd8a8 1114The "list" action in our Books controller showed up with a path of
1115C</books/list>.
4d583dd8 1116
1117=back
1118
64ccd8a8 1119Point your browser to L<http://localhost:3000> and you should still get
1120the Catalyst welcome page.
4d583dd8 1121
64ccd8a8 1122Next, to view the book list, change the URL in your browser to
1123L<http://localhost:3000/books/list>. You should get a list of the five
1124books loaded by the C<myapp01.sql> script above, with TTSite providing
1125the formatting for the very simple output we generated in our template.
1126The count and space-separated list of author last names appear on the
1127end of each row.
4d583dd8 1128
64ccd8a8 1129Also notice in the output of the C<script/myapp_server.pl> that DBIC
1130used the following SQL to retrieve the data:
4d583dd8 1131
1132 SELECT me.id, me.title, me.rating FROM books me
1133
64ccd8a8 1134Along with a list of the following commands to retrieve the authors for
1135each book (the lines have been "word wrapped" here to improve
1136legibility):
4d583dd8 1137
1138 SELECT author.id, author.first_name, author.last_name
1139 FROM book_authors me
1140 JOIN authors author ON ( author.id = me.author_id )
1141 WHERE ( me.book_id = ? ): `1'
1142
208513f1 1143You should see 5 such lines of debug output as DBIC fetches the author
1144information for each book.
4d583dd8 1145
1146
770fdaa9 1147=head1 USING THE DEFAULT TEMPLATE NAME
1148
1149By default, C<Catalyst::View::TT> will look for a template that uses the
1150same name as your controller action, allowing you to save the step of
1151manually specifying the template name in each action. For example, this
1152would allow us to remove (or comment out) the
1153C<$c-E<gt>stash-E<gt>{template} = 'books/list.tt2';> line of our
1154C<list> action in the Books controller. Open
1155C<lib/MyApp/Controller/Books.pm> in your editor and update it to
1156match the following:
1157
1158 =head2 list
1159
1160 Fetch all book objects and pass to books/list.tt2 in stash to be displayed
1161
1162 =cut
1163
1164 sub list : Local {
1165 # Retrieve the usual perl OO '$self' for this object. $c is the Catalyst
1166 # 'Context' that's used to 'glue together' the various components
1167 # that make up the application
1168 my ($self, $c) = @_;
1169
1170 # Retrieve all of the book records as book model objects and store in the
1171 # stash where they can be accessed by the TT template
1172 $c->stash->{books} = [$c->model('MyAppDB::Book')->all];
1173
1174 # Automatically look for a template of 'books/list.tt2' template
1175 # (if TEMPLATE_EXTENSION is set to '.tt2')
1176 }
1177
1178C<Catalyst::View::TT> defaults to looking for a template with no
1179extension. In our case, we need to override this to look for an
1180extension of C<.tt2>. Open C<lib/MyApp/View/TT.pm> and add the
1181C<TEMPLATE_EXTENSION> definition as follows:
1182
1183 __PACKAGE__->config({
1184 CATALYST_VAR => 'Catalyst',
1185 INCLUDE_PATH => [
1186 MyApp->path_to( 'root', 'src' ),
1187 MyApp->path_to( 'root', 'lib' )
1188 ],
1189 PRE_PROCESS => 'config/main',
1190 WRAPPER => 'site/wrapper',
1191 ERROR => 'error.tt2',
1192 TIMER => 0,
1193 TEMPLATE_EXTENSION => '.tt2',
1194 });
1195
1196You should now be able to restart the development server as per the
1197previous section and access the L<http://localhost:3000/books/list>
1198as before.
1199
1200Although this can be a valuable technique to establish a default
1201template for each of your actions, the remainder of the tutorial
1202will manually assign the template name to
1203C<$c-E<gt>stash-E<gt>{template}> in each action in order to make
1204the logic as conspicuous as possible.
1205
1206
4d583dd8 1207=head1 AUTHOR
1208
1209Kennedy Clark, C<hkclark@gmail.com>
1210
c608fae5 1211Please report any errors, issues or suggestions to the author. The
7d310f12 1212most recent version of the Catalyst Tutorial can be found at
c608fae5 1213L<http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst-Runtime/lib/Catalyst/Manual/Tutorial/>.
4d583dd8 1214
71dedf57 1215Copyright 2006, Kennedy Clark, under Creative Commons License
1216(L<http://creativecommons.org/licenses/by-nc-sa/2.5/>).
4d583dd8 1217