Remove extraneous 'TT bogus assignment' and update comment to still explain situation...
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Manual / Tutorial / BasicCRUD.pod
index f6685ec..493c868 100644 (file)
@@ -45,7 +45,7 @@ L<AdvancedCRUD|Catalyst::Manual::Tutorial::AdvancedCRUD>
 
 =item 9
 
-L<Appendicies|Catalyst::Manual::Tutorial::Appendicies>
+L<Appendices|Catalyst::Manual::Tutorial::Appendices>
 
 =back
 
@@ -56,7 +56,7 @@ L<Appendicies|Catalyst::Manual::Tutorial::Appendicies>
 This part of the tutorial builds on the fairly primitive application
 created in Part 2 to add basic support for Create, Read, Update, and
 Delete (CRUD) of C<Book> objects.  Note that the 'list' function in Part
-2 already implements the Read portion of Crud (although Read normally
+2 already implements the Read portion of CRUD (although Read normally
 refers to reading a single object; you could implement full read
 functionality using the techniques introduced below).  This section will
 focus on the Create and Delete aspects of CRUD.  More advanced
@@ -67,9 +67,7 @@ B<TIP>: Note that all of the code for this part of the tutorial can be
 pulled from the Catalyst Subversion repository in one step with the
 following command:
 
-    svn checkout http://dev.catalyst.perl.org/repos/Catalyst/trunk/examples/Tutorial@###
-    IMPORTANT: Does not work yet.  Will be completed for final version.
-
+    svn co http://dev.catalyst.perl.org/repos/Catalyst/tags/examples/Tutorial/5.7X/BasicCRUD MyApp
 
 
 =head1 FORMLESS SUBMISSION
@@ -85,21 +83,22 @@ Edit C<lib/MyApp/Controller/Books.pm> and enter the following method:
 
     =head2 url_create
     
-    Create a book with the supplied title, rating and author
+    Create a book with the supplied title, rating, and author
     
     =cut
     
     sub url_create : Local {
-        # In addition to self & context, get the title, rating & author_id args
-        # from the URL.  Note that Catalyst automatically puts extra information
-        # after the "/<controller_name>/<action_name/" into @_
+        # In addition to self & context, get the title, rating, & 
+        # author_id args from the URL.  Note that Catalyst automatically 
+        # puts extra information after the "/<controller_name>/<action_name/" 
+        # into @_
         my ($self, $c, $title, $rating, $author_id) = @_;
     
         # Call create() on the book model object. Pass the table 
         # columns/field values we want to set as hash values
         my $book = $c->model('MyAppDB::Book')->create({
-                title   => $title,
-                rating  => $rating
+                title  => $title,
+                rating => $rating
             });
         
         # Add a record to the join table for this book, mapping to 
@@ -141,40 +140,51 @@ Edit C<root/src/books/create_done.tt2> and then enter:
     [% # optional, but prevents "massive indenting" of deeply nested objects -%]
     [% USE Dumper(Indent=1) -%]
     
-    [% # Set the page title -%]
+    [% # Set the page title.  META can 'go back' and set values in templates -%]
+    [% # that have been processed 'before' this template (here it's for      -%]
+    [% # root/lib/site/html and root/lib/site/header).  Note that META on    -%]
+    [% # simple strings (e.g., no variable interpolation).                   -%]
     [% META title = 'Book Created' %]
     
-    [% # Output information about the record that was added.  Note use  -%]
-    [% # of 'first' to only list the first author (if > 1 author).      -%] 
-    <p>Added book '[% book.title %]' by '[% book.authors.first.last_name %]'
+    [% # Output information about the record that was added.  First title.       -%]
+    <p>Added book '[% book.title %]'
+    
+    [% # Output the last name of the first author.  This is complicated by an    -%]
+    [% # issue in TT 2.15 where blessed hash objects are not handled right.      -%]
+    [% # First, fetch 'book.authors' from the DB once.                           -%]
+    [% authors = book.authors %]
+    [% # Now use IF statements to test if 'authors.first' is "working". If so,   -%]
+    [% # we use it.  Otherwise we use a hack that seems to keep TT 2.15 happy.   -%]
+    by '[% authors.first.last_name IF authors.first; 
+           authors.list.first.value.last_name IF ! authors.first %]'
+    
+    [% # Output the rating for the book that was added -%]
     with a rating of [% book.rating %].</p>
     
     [% # Provide a link back to the list page                                    -%]
     [% # 'uri_for()' builds a full URI; e.g., 'http://localhost:3000/books/list' -%]
     <p><a href="[% Catalyst.uri_for('/books/list') %]">Return to list</a></p>
     
-    [% # Try out the TT Dumper -%]
+    [% # Try out the TT Dumper (for development only!) -%]
     <pre>
     Dump of the 'book' variable:
     [% Dumper.dump(book) %]
     </pre>
 
-The TT C<USE> directive allows access to a variety of plugin modules (we
-are talking TT plugins here, not Catalyst plugins) to add extra
-functionality to the base TT capabilities.  Here, the plugin allows
-L<Data::Dumper|Data::Dumper> "pretty printing" of objects and variables.
-Other than that, the rest of the code should be familiar from the
-examples in Part 2.
+The TT C<USE> directive allows access to a variety of plugin modules (TT
+plugins, that is, not Catalyst plugins) to add extra functionality to
+the base TT capabilities.  Here, the plugin allows L<Data::Dumper>
+"pretty printing" of objects and variables.  Other than that, the rest
+of the code should be familiar from the examples in Part 2.
 
 B<IMPORTANT NOTE> As mentioned earlier, the C<MyApp::View::TT.pm> view
 class created by TTSite redefines the name used to access the Catalyst
 context object in TT templates from the usual C<c> to C<Catalyst>.
 
-
 =head2 Try the C<url_create> Feature
 
 If the application is still running from before, use C<Ctrl-C> to kill
-it.  Then restart the server:
+it. Then restart the server:
 
     $ script/myapp_server.pl
 
@@ -184,7 +194,7 @@ output.
 B<TIP>: You can use C<script/myapp_server.pl -r> to have the development
 server auto-detect changed files and reload itself (if your browser acts
 odd, you should also try throwing in a C<-k>).  If you make changes to
-just the TT templates, you do not need to reload the development server
+the TT templates only, you do not need to reload the development server
 (only changes to "compiled code" such as Controller and Model C<.pm>
 files require a reload).
 
@@ -205,7 +215,6 @@ are now six books shown (if necessary, Shift-Reload your browser at the
 C</books/list> page).
 
 
-
 =head1 MANUALLY BUILDING A CREATE FORM
 
 Although the C<url_create> action in the previous step does begin to
@@ -231,14 +240,13 @@ Edit C<lib/MyApp/Controller/Books.pm> and add the following method:
         $c->stash->{template} = 'books/form_create.tt2';
     }
 
-This action merely invokes a view containing a book creation form.
-
+This action simply invokes a view containing a book creation form.
 
 =head2 Add a Template for the Form
 
 Open C<root/src/books/form_create.tt2> in your editor and enter:
 
-    [% META title = 'Book Create' -%]
+    [% META title = 'Manual Form Book Create' -%]
     
     <form method="post" action="[% Catalyst.uri_for('form_create_do') %]">
     <table>
@@ -252,11 +260,10 @@ Open C<root/src/books/form_create.tt2> in your editor and enter:
 Note that we have specified the target of the form data as
 C<form_create_do>, the method created in the section that follows.
 
-
 =head2 Add Method to Process Form Values and Update Database
 
 Edit C<lib/MyApp/Controller/Books.pm> and add the following method to
-save the form information to the databse:
+save the form information to the database:
 
     =head2 form_create_do
     
@@ -283,7 +290,7 @@ save the form information to the databse:
         # Store new model object in stash
         $c->stash->{book} = $book;
     
-        # Avoid Data::Dumper issue mention earlier
+        # Avoid Data::Dumper issue mentioned earlier
         # You can probably omit this    
         $Data::Dumper::Useperl = 1;
     
@@ -294,7 +301,8 @@ save the form information to the databse:
 
 =head2 Test Out The Form
 
-If the application is still running from before, use C<Ctrl-C> to kill it.  Then restart the server:
+If the application is still running from before, use C<Ctrl-C> to kill
+it.  Then restart the server:
 
     $ script/myapp_server.pl
 
@@ -305,10 +313,8 @@ C<create_done.tt2> template seen in earlier examples.  Finally, click
 "Return to list" to view the full list of books.
 
 B<Note:> Having the user enter the primary key ID for the author is
-obviously a bit crude; we will address this concern with a drop-down
-list in Part 8.
-
-
+obviously crude; we will address this concern with a drop-down list in
+Part 8.
 
 =head1 A SIMPLE DELETE FEATURE
 
@@ -339,16 +345,19 @@ and 2) the four lines for the Delete link near the bottom).
         <td>[% book.title %]</td>
         <td>[% book.rating %]</td>
         <td>
-          [% # Print author count in parens. 'book.authors' uses the 'many_to_many' -%]
-          [% # relationship to retrieve all of the authors of a book. 'size' is a   -%]
-          [% # TT VMethod to get the number of elements in a list.                  -%]
-          ([% book.authors.size %])
-          [% # Use an alternate form of a FOREACH loop to display authors.          -%]
-          [% # _ below is the TT string concatenation operator.                     -%]
-          [% author.last_name _' ' FOREACH author = book.authors %]
-          [% # Note: if many_to_many relationship not used in Authors.pm, you could -%]
-          [% # have used the following to 'walk' through the 'join table objects'   -%]
-          [% # bk_author.author.last_name _' ' FOREACH bk_author = book.book_authors %]
+          [% # First initialize a TT variable to hold a list.  Then use a TT FOREACH -%]
+          [% # loop in 'side effect notation' to load just the last names of the     -%]
+          [% # authors into the list.  Note that the 'push' TT vmethod does not      -%]
+          [% # a value, so nothing will be printed here.  But, if you have something -%]
+          [% # in TT that does return a method and you don't want it printed, you    -%]
+          [% # can: 1) assign it to a bogus value, or 2) use the CALL keyword to     -%]
+          [% # call it and discard the return value.                                 -%]
+          [% tt_authors = [ ];
+             tt_authors.push(author.last_name) FOREACH author = book.authors %]
+          [% # Now use a TT 'virtual method' to display the author count             -%]
+          ([% tt_authors.size %])
+          [% # Use another TT vmethod to join & print the names & comma separators   -%]
+          [% tt_authors.join(', ') %]
         </td>
         <td>
           [% # Add a link to delete a book %]
@@ -362,13 +371,12 @@ The additional code is obviously designed to add a new column to the
 right side of the table with a C<Delete> "button" (for simplicity, links
 will be used instead of full HTML buttons).
 
-
 =head2 Add a Delete Action to the Controller
 
 Open C<lib/MyApp/Controller/Books.pm> in your editor and add the
 following method:
 
-    =head2 Delete 
+    =head2 delete 
     
     Delete a book
         
@@ -431,10 +439,10 @@ with a list of the six remaining books.
 
 Kennedy Clark, C<hkclark@gmail.com>
 
-Please report any errors, issues or suggestions to the author.
+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-Runtime/lib/Catalyst/Manual/Tutorial/>.
 
 Copyright 2006, Kennedy Clark, under Creative Commons License
 (L<http://creativecommons.org/licenses/by-nc-sa/2.5/>).
 
-Version: .94
-