rollback to use Catalyst qw/@plugins/
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / Tutorial / MoreCatalystBasics.pod
index c52f435..2c22731 100644 (file)
@@ -87,7 +87,7 @@ tutorial):
     $ cd MyApp
 
 This creates a similar skeletal structure to what we saw in Part 2 of 
-the tutorial, except with C<MyApp> or C<myapp> substituted for 
+the tutorial, except with C<MyApp> and C<myapp> substituted for 
 C<Hello> and C<hello>.
 
 
@@ -133,12 +133,40 @@ free to make use of it in your own projects.
 L<Catalyst::Plugin::ConfigLoader|Catalyst::Plugin::ConfigLoader>
 
 C<ConfigLoader> provides an automatic way to load configurable
-parameters for your application from a central YAML file (versus having
-the values hard-coded inside your Perl modules).  If you have not been
-exposed to YAML before, it is a human-readable data serialization format
-that can be used to read (and write) values to/from text files.  We will
-see how to use this feature of Catalyst during the authentication and
-authorization sections (Part 5 and Part 6).
+parameters for your application from a central
+L<Config::General|Config::General> file (versus having the values
+hard-coded inside your Perl modules).  Config::General uses syntax
+very similar to Apache configuration files.  We will see how to use
+this feature of Catalyst during the authentication and authorization
+sections (Part 5 and Part 6).
+
+B<IMPORTANT NOTE:> If you are following along in Ubuntu 8.04 or
+otherwise using a version of L<Catalyst::Devel|Catalyst::Devel> prior
+to version 1.06, you need to be aware that Catalyst changed from a
+default format of YAML to the more straightforward C<Config::General>
+format.  Because Catalyst has long supported both formats, this
+tutorial will simply use a configuration file called C<myapp.conf>
+instead of C<myapp.yml> and Catatlyst will automcatically use the new
+format.  Just be aware that earlier versions of Catalyst will still
+create the C<myapp.yml> file and that you will need to B<remove
+C<myapp.yml>> and create a new C<myapp.conf> file by hand, but
+otherwise this transition is very painless.  The default contents of
+C<myapp.conf> should only consist of one line: C<name MyApp>.  Also be
+aware that you can continue to use any format supported by
+L<Catalyst::Plugin::ConfigLoader|Catalyst::Plugin::ConfigLoader> and
+L<Config::Any|Config::Any>, including YAML -- Catalyst will
+automatically look for any of the supported configuration file
+formats.
+
+B<TIP>: This script can be useful for converting between configuration 
+formats:
+
+    perl -Ilib -e 'use MyApp; use Config::General; 
+        Config::General->new->save_file("myapp.conf", MyApp->config);'
+
+B<NOTE:> The default C<myapp.conf> should look like:
+
+    name   MyApp
 
 =item *
 
@@ -158,12 +186,12 @@ with:
 Replace it with:
 
     use Catalyst qw/
-            -Debug
-            ConfigLoader
-            Static::Simple
-            
-            StackTrace
-            /;
+                   -Debug
+                   ConfigLoader
+                   Static::Simple
+
+                   StackTrace
+                  /;
 
 This tells Catalyst to start using one new plugin:
 
@@ -180,6 +208,10 @@ Note: L<StackTrace|Catalyst::Plugin::StackTrace> output appears in your
 browser, not in the console window from which you're running your
 application, which is where logging output usually goes.
 
+B<Note:> You will want to disable 
+L<StackTrace|Catalyst::Plugin::StackTrace> before you put your 
+application into production, but it can be helpful during development.
+
 =back
 
 Note that when specifying plugins on the C<use Catalyst> line, you can
@@ -220,7 +252,7 @@ to the controller:
     
         # Retrieve all of the book records as book model objects and store in the
         # stash where they can be accessed by the TT template
-        $c->stash->{books} = [$c->model('MyAppDB::Books')->all];
+        $c->stash->{books} = [$c->model('DB::Books')->all];
         
         # Set the TT template to use.  You will almost always want to do this
         # in your action methods (action methods respond to user input in
@@ -229,7 +261,7 @@ to the controller:
     }
 
 B<Note:> This won't actually work yet since you haven't set up your 
-model yet.
+model yet.  We will be covering the model soon.
 
 B<Note:> Programmers experienced with object-oriented Perl should 
 recognize C<$self> as a reference to the object where this method was 
@@ -239,20 +271,20 @@ C<$context>).  The Context object is automatically passed to all
 Catalyst components.  It is used to pass information between 
 components and provide access to Catalyst and plugin functionality.
 
-B<TIP>: You may see the C<$c-E<gt>model('MyAppDB::Book')> used above
-written as C<$c-E<gt>model('MyAppDB')-E<gt>resultset('Book)>.  The two
+B<TIP>: You may see the C<$c-E<gt>model('DB::Book')> used above
+written as C<$c-E<gt>model('DB')-E<gt>resultset('Book')>.  The two
 are equivalent.
 
 B<Note:> Catalyst actions are regular Perl methods, but they make use 
 of Nicholas Clark's C<attributes> module (that's the C<: Local> next 
 to the C<sub list> in the code above) to provide additional 
 information to the Catalyst dispatcher logic.  Many newer Catalyst 
-applications are switching to the use of "Literal" C<: Path> actions 
+applications are switching to the use of "Literal" C<:Path> actions 
 and C<Args> attribute in lieu of C<: Local> and C<: Private>.  For 
-example, C<sub any_method : Path Args(0)> can be used instead of 
+example, C<sub any_method :Path :Args(0)> can be used instead of 
 C<sub index :Private> (because no path was supplied to C<Path> it 
 matches the "empty" URL in the namespace of that module... the same 
-thing C<sub index> would do) or C<sub list : Path('list') Args(0)> 
+thing C<sub index> would do) or C<sub list :Path('list') :Args(0)> 
 could be used instead of the C<sub list : Local> above (the C<list> 
 argument to C<Path> would make it match on the URL C<list> under 
 C<books>, the namespace of the current module).  See "Action Types" in 
@@ -273,11 +305,11 @@ possibly using other display output- generation systems.  As with
 virtually every aspect of Catalyst, options abound when it comes to 
 the specific view technology you adopt inside your application. 
 However, most Catalyst applications use the Template Toolkit, known as 
-TT (for more information on TT, see L<http://www.template-
-toolkit.org>). Other popular view technologies include Mason 
-(L<http://www.masonhq.com> and L<http://www.masonbook.com>) and 
-L<HTML::Template|HTML::Template> (L<http://html-
-template.sourceforge.net>).
+TT (for more information on TT, see 
+L<http://www.template-toolkit.org>). Other popular view technologies 
+include Mason (L<http://www.masonhq.com> and 
+L<http://www.masonbook.com>) and L<HTML::Template> 
+(L<http://html-template.sourceforge.net>).
 
 =head2 Create a Catalyst View Using C<TTSite>
 
@@ -329,30 +361,12 @@ directories that can be used to customize the look and feel of your
 application.  Also take a look at C<lib/MyApp/View/TT.pm> for config
 values set by the C<TTSite> helper.
 
-B<TIP>: Note that TTSite does one thing that could confuse people who
-are used to the normal C<TT> Catalyst view: it redefines the Catalyst
-context object in templates from its usual C<c> to C<Catalyst>. When
-looking at other Catalyst examples, remember that they almost always use
-C<c>.  Note that Catalyst and TT I<do not complain> when you use the
-wrong name to access the context object...TT simply outputs blanks for
-that bogus logic (see next tip to change this behavior with TT C<DEBUG>
-options).  Finally, be aware that this change in name I<only>
-applies to how the context object is accessed inside your TT templates;
-your controllers will continue to use C<$c> (or whatever name you use
-when fetching the reference from C<@_> inside your methods). (You can
-change back to the "default" behavior be removing the C<CATALYST_VAR>
-line from C<lib/MyApp/View/TT.pm>, but you will also have to edit
-C<root/lib/config/main> and C<root/lib/config/url>.  If you do this, be
-careful not to have a collision between your own C<c> variable and the
-Catalyst C<c> variable.)
-
 B<TIP>: When troubleshooting TT it can be helpful to enable variable
 C<DEBUG> options.  You can do this in a Catalyst environment by adding
 a C<DEBUG> line to the C<__PACKAGE__->config> declaration in 
 C<lib/MyApp/View/TT.pm>:
 
     __PACKAGE__->config({
-        CATALYST_VAR => 'Catalyst',
         ...
         DEBUG        => 'undef',
         ...
@@ -363,7 +377,7 @@ of the package where it is used.  Therefore, in C<TT.pm>,
 C<__PACKAGE__> is equivalent to C<TT>.
 
 There are a variety of options you can use, such as 'undef', 'all', 
-'service', 'context', 'parser', 'provider', and 'service'.  See
+'service', 'context', 'parser' and 'provider'.  See
 L<Template::Constants> for more information (remove the C<DEBUG_>
 portion of the name shown in the TT docs and convert to lower case
 for use inside Catalyst).
@@ -455,7 +469,7 @@ for details and examples).  In addition to the usual C<Template> module
 Pod documentation, you can access the TT manual at
 L<http://www.template-toolkit.org/docs/default/>.
 
-B<NOTE>: The C<TTSite> helper creates several TT files using an
+B<NOTE:> The C<TTSite> helper creates several TT files using an
 extension of C<.tt2>. Most other Catalyst and TT examples use an
 extension of C<.tt>.  You can use either extension (or no extension at
 all) with TTSite and TT, just be sure to use the appropriate extension
@@ -570,38 +584,36 @@ in the past, Matt Trout's L<DBIx::Class|DBIx::Class> (abbreviated
 as "DBIC") has rapidly emerged as the Perl-based ORM technology of choice.  
 Most new Catalyst applications rely on DBIC, as will this tutorial.
 
-=head2 Create a Dynamic DBIC Model
+=head2 Create a dynamic DBIC Model
 
 Use the C<create=dynamic> model helper option to build a model that 
 dynamically reads your database structure every time the application
 starts:
 
-    $ script/myapp_create.pl model MyAppDB DBIC::Schema MyApp::Schema::MyAppDB create=dynamic dbi:SQLite:myapp.db
-     exists "/home/me/MyApp/script/../lib/MyApp/Model"
-     exists "/home/me/MyApp/script/../t"
-    created "/home/me/MyApp/script/../lib/MyApp/Schema"
-    created "/home/me/MyApp/script/../lib/MyApp/Schema/MyAppDB.pm"
-    created "/home/me/MyApp/script/../lib/MyApp/Model/MyAppDB.pm"
-    created "/home/me/MyApp/script/../t/model_MyAppDB.t"
+    $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema create=dynamic dbi:SQLite:myapp.db
+     exists "/home/kclark/dev/MyApp/script/../lib/MyApp/Model"
+     exists "/home/kclark/dev/MyApp/script/../t"
+     exists "/home/kclark/dev/MyApp/script/../lib/MyApp"
+    created "/home/kclark/dev/MyApp/script/../lib/MyApp/Schema.pm"
+    created "/home/kclark/dev/MyApp/script/../lib/MyApp/Model/DB.pm"
+    created "/home/kclark/dev/MyApp/script/../t/model_DB.t"
 
 
-C<MyAppDB> is the name of the model class to be created by the helper in 
+C<DB> is the name of the model class to be created by the helper in 
 C<lib/MyApp/Model> (Catalyst has a separate directory under C<lib/MyApp> 
-for each of the three parts of MVC: C<Model>, C<View>, and C<Controller> 
-[although older Catalyst applications often use the directories C<M>, 
-C<V>, and C<C>]).  C<DBIC::Schema> is the type of the model to create. 
-C<MyApp::Schema::MyAppDB> is the name of the DBIC schema file written to 
-C<lib/MyApp/Schema/MyAppDB.pm>.  Because we specified C<create=dynamic> 
+for each of the three parts of MVC: C<Model>, C<View>, and C<Controller>).  
+C<DBIC::Schema> is the type of the model to create. 
+C<MyApp::Schema> is the name of the DBIC schema file written to 
+C<lib/MyApp/Schema.pm>.  Because we specified C<create=dynamic> 
 to the helper, it use L<DBIx::Class::Schema::Loader> to dynamically load 
 the schema information from the database every time the application 
 starts.  And finally, C<dbi:SQLite:myapp.db> is the standard DBI connect 
 string for use with SQLite.
 
-B<NOTE>: Although the C<create=dynamic> option to the DBIC helper 
-makes for a nifty demonstration, is not suitable for real world 
-applications. Moreover, it may not be supported in future versions of 
-DBIC.  After this demonstration, please use the C<create=static> 
-option that we switch to below.
+B<NOTE:> Although the C<create=dynamic> option to the DBIC helper
+makes for a nifty demonstration, is only really suitable for very
+small applications. After this demonstration, you should almost always
+use the C<create=static> option that we switch to below.
 
 
 =head1 RUN THE APPLICATION
@@ -616,7 +628,7 @@ This assumes you are using BASH as your shell -- adjust accordingly if
 you are using a different shell (for example, under tcsh, use
 C<setenv DBIC_TRACE 1>).
 
-B<NOTE>: You can also set this in your code using
+B<NOTE:> You can also set this in your code using
 C<$class-E<gt>storage-E<gt>debug(1);>.  See
 L<DBIx::Class::Manual::Troubleshooting> for details (including options
 to log to file instead of displaying to the Catalyst development server
@@ -640,17 +652,17 @@ Your development server log output should display something like:
     [debug] Loaded dispatcher "Catalyst::Dispatcher"
     [debug] Loaded engine "Catalyst::Engine::HTTP"
     [debug] Found home "/home/me/MyApp"
-    [debug] Loaded Config "/home/me/MyApp/myapp.yml"
+    [debug] Loaded Config "/home/me/MyApp/myapp.conf"
     [debug] Loaded components:
     .-----------------------------------------------------------------+----------.
     | Class                                                           | Type     |
     +-----------------------------------------------------------------+----------+
     | MyApp::Controller::Books                                        | instance |
     | MyApp::Controller::Root                                         | instance |
-    | MyApp::Model::MyAppDB                                           | instance |
-    | MyApp::Model::MyAppDB::Authors                                  | class    |
-    | MyApp::Model::MyAppDB::BookAuthors                              | class    |
-    | MyApp::Model::MyAppDB::Books                                    | class    |
+    | MyApp::Model::DB                                                | instance |
+    | MyApp::Model::DB::Authors                                       | class    |
+    | MyApp::Model::DB::BookAuthors                                   | class    |
+    | MyApp::Model::DB::Books                                         | class    |
     | MyApp::View::TT                                                 | instance |
     '-----------------------------------------------------------------+----------'
     
@@ -674,7 +686,7 @@ Your development server log output should display something like:
     [info] MyApp powered by Catalyst 5.7011
     You can connect to your server at http://localhost:3000
 
-B<NOTE>: Be sure you run the C<script/myapp_server.pl> command from 
+B<NOTE:> Be sure you run the C<script/myapp_server.pl> command from 
 the 'base' directory of your application, not inside the C<script> 
 directory itself or it will not be able to locate the C<myapp.db> 
 database file.  You can use a fully qualified or a relative path to 
@@ -689,8 +701,8 @@ Some things you should note in the output above:
 
 Catalyst::Model::DBIC::Schema dynamically created three model classes, 
 one to represent each of the three tables in our database 
-(C<MyApp::Model::MyAppDB::Authors>, C<MyApp::Model::MyAppDB::BookAuthors>,
-and C<MyApp::Model::MyAppDB::Books>).
+(C<MyApp::Model::DB::Authors>, C<MyApp::Model::DB::BookAuthors>,
+and C<MyApp::Model::DB::Books>).
 
 =item * 
 
@@ -715,7 +727,7 @@ used the following SQL to retrieve the data:
 
 because we enabled DBIC_TRACE.
 
-You now the beginnings of a simple but workable web application. 
+You now have the beginnings of a simple but workable web application.
 Continue on to future sections and we will develop the application
 more fully.
 
@@ -732,31 +744,31 @@ will use static schema files for more control.  This is typical of most
 One option would be to create a separate schema file for each table in
 the database, however, lets use the same L<DBIx::Class::Schema::Loader>
 used earlier with C<create=dynamic> to build the static files for us.
-First, lets remove the schema file created in Part 2:
+First, lets remove the schema file created earlier:
 
-    $ rm lib/MyApp/Schema/MyAppDB.pm 
+    $ rm lib/MyApp/Schema.pm 
 
 Now regenerate the schema using the C<create=static> option:
 
-    $ script/myapp_create.pl model MyAppDB DBIC::Schema MyApp::Schema::MyAppDB create=static dbi:SQLite:myapp.db
-     exists "/home/me/MyApp/script/../lib/MyApp/Model"
-     exists "/home/me/MyApp/script/../t"
-    Dumping manual schema for MyApp::Schema::MyAppDB to directory /home/me/MyApp/script/../lib ...
+    $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema create=static dbi:SQLite:myapp.db
+     exists "/home/kclark/dev/MyApp/script/../lib/MyApp/Model"
+     exists "/home/kclark/dev/MyApp/script/../t"
+    Dumping manual schema for MyApp::Schema to directory /home/kclark/dev/MyApp/script/../lib ...
     Schema dump completed.
-     exists "/home/me/MyApp/script/../lib/MyApp/Model/MyAppDB.pm"
+     exists "/home/kclark/dev/MyApp/script/../lib/MyApp/Model/DB.pm"
 
-We could have also deleted C<lib/MyApp/Model/MyAppDB.pm>, but it would 
+We could have also deleted C<lib/MyApp/Model/DB.pm>, but it would 
 have regenerated the same file (note the C<exists> in the output above).
-If you take a look at C<lib/MyApp/Model/MyAppDB.pm>, it simply contains
-a reference to the actual schema file in C<lib/MyApp/Schema/MyAppDB.pm>
+If you take a look at C<lib/MyApp/Model/DB.pm>, it simply contains
+a reference to the actual schema file in C<lib/MyApp/Schema.pm>
 along with the database connect string.
 
 If you look in the C<lib/MyApp/Schema> directory, you will find that 
-C<MyAppDB.pm> is no longer using L<DBIx::Class::Schema::Loader> as its 
+C<DB.pm> is no longer using L<DBIx::Class::Schema::Loader> as its 
 base class (L<DBIx::Class::Schema::Loader> is only being used by the 
 helper to load the schema once and then create the static files for us) 
 and that it only contains a call to the C<load_classes> method.  You 
-will also find that C<lib/MyApp/Schema> contains a C<MyAppDB> 
+will also find that C<lib/MyApp/Schema> contains a C<Schema> 
 subdirectory, with one file inside this directory for each of the tables 
 in our simple database (C<Authors.pm>, C<BookAuthors.pm>, and 
 C<Books.pm>).  These three files were created based on the information
@@ -771,10 +783,10 @@ structure get updated.
 
 Also note the "flow" of the model information across the various files 
 and directories.  Catalyst will initially load the model from 
-C<lib/MyApp/Model/MyAppDB.pm>.  This file contains a reference to
-C<lib/MyApp/Schema/MyAppDB.pm>, so that file is loaded next.  Finally,
+C<lib/MyApp/Model/DB.pm>.  This file contains a reference to
+C<lib/MyApp/Schema.pm>, so that file is loaded next.  Finally,
 the call to C<load_classes> in that file will load each of the 
-table-specific "results source" files from the C<lib/MyApp/Schema/MyAppDB>
+table-specific "results source" files from the C<lib/MyApp/Schema>
 subdirectory.  These three table-specific DBIC schema files will then be 
 used to create three table-specific Catalyst models every time the 
 application starts (you can see these three model files listed in
@@ -785,7 +797,7 @@ the debug output generated when you launch the application).
 
 
 Let's manually add some relationship information to the auto-generated
-schema files.  First edit C<lib/MyApp/Schema/MyAppDB/Books.pm> and
+schema files.  First edit C<lib/MyApp/Schema/Books.pm> and
 add the following text below the C<# You can replace this text...> 
 comment:
 
@@ -798,7 +810,7 @@ comment:
     #     1) Name of relationship, DBIC will create accessor with this name
     #     2) Name of the model class referenced by this relationship
     #     3) Column name in *foreign* table
-    __PACKAGE__->has_many(book_authors => 'MyApp::Schema::MyAppDB::BookAuthors', 'book_id');
+    __PACKAGE__->has_many(book_authors => 'MyApp::Schema::BookAuthors', 'book_id');
     
     # many_to_many():
     #   args:
@@ -826,7 +838,7 @@ shorter C<$book-E<gt>authors-E<gt>first-E<gt>last_name>. Note that you
 cannot define a C<many_to_many> relationship without also having the 
 C<has_many> relationship in place.
 
-Then edit C<lib/MyApp/Schema/MyAppDB/Authors.pm> and add relationship
+Then edit C<lib/MyApp/Schema/Authors.pm> and add relationship
 information as follows (again, be careful to put in above the C<1;> but
 below the C<# DO NOT MODIFY THIS OR ANYTHING ABOVE!> comment):
 
@@ -839,7 +851,7 @@ below the C<# DO NOT MODIFY THIS OR ANYTHING ABOVE!> comment):
     #     1) Name of relationship, DBIC will create accessor with this name
     #     2) Name of the model class referenced by this relationship
     #     3) Column name in *foreign* table
-    __PACKAGE__->has_many(book_author => 'MyApp::Schema::MyAppDB::BookAuthors', 'author_id');
+    __PACKAGE__->has_many(book_author => 'MyApp::Schema::BookAuthors', 'author_id');
     
     # many_to_many():
     #   args:
@@ -850,7 +862,7 @@ below the C<# DO NOT MODIFY THIS OR ANYTHING ABOVE!> comment):
     __PACKAGE__->many_to_many(books => 'book_author', 'book');
 
 Finally, do the same for the "join table," 
-C<lib/MyApp/Schema/MyAppDB/BookAuthors.pm>:
+C<lib/MyApp/Schema/BookAuthors.pm>:
 
     #
     # Set relationships:
@@ -861,14 +873,14 @@ C<lib/MyApp/Schema/MyAppDB/BookAuthors.pm>:
     #     1) Name of relationship, DBIC will create accessor with this name
     #     2) Name of the model class referenced by this relationship
     #     3) Column name in *this* table
-    __PACKAGE__->belongs_to(book => 'MyApp::Schema::MyAppDB::Books', 'book_id');
+    __PACKAGE__->belongs_to(book => 'MyApp::Schema::Books', 'book_id');
     
     # belongs_to():
     #   args:
     #     1) Name of relationship, DBIC will create accessor with this name
     #     2) Name of the model class referenced by this relationship
     #     3) Column name in *this* table
-    __PACKAGE__->belongs_to(author => 'MyApp::Schema::MyAppDB::Authors', 'author_id');
+    __PACKAGE__->belongs_to(author => 'MyApp::Schema::Authors', 'author_id');
 
 
 =head1 RUN THE APPLICATION
@@ -1031,7 +1043,7 @@ has changed):
     
         # Retrieve all of the book records as book model objects and store in the
         # stash where they can be accessed by the TT template
-        $c->stash->{books} = [$c->model('MyAppDB::Books')->all];
+        $c->stash->{books} = [$c->model('DB::Books')->all];
     
         # Set the TT template to use.  You will almost always want to do this
         # in your action methods (actions methods respond to user input in
@@ -1091,6 +1103,6 @@ Please report any errors, issues or suggestions to the author.  The
 most recent version of the Catalyst Tutorial can be found at
 L<http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst-Manual/lib/Catalyst/Manual/Tutorial/>.
 
-Copyright 2006, Kennedy Clark, under Creative Commons License
+Copyright 2006-2008, Kennedy Clark, under Creative Commons License
 (L<http://creativecommons.org/licenses/by-nc-sa/2.5/>).