Switch from 'sub base :Path :Args(0)' to 'sub index : Private' for
Kennedy Clark [Wed, 5 Jul 2006 21:29:50 +0000 (21:29 +0000)]
Login and Logout controllers
Minor link fix in Auth.pod

Split out tests for title & author in add of test script.
Fix whitespace in testing script.

Misc fixes to AdvancedCRUD.pod.

lib/Catalyst/Manual/Tutorial/AdvancedCRUD.pod
lib/Catalyst/Manual/Tutorial/Authentication.pod
lib/Catalyst/Manual/Tutorial/Testing.pod

index eedde71..c68d6c8 100644 (file)
@@ -60,23 +60,24 @@ forms and model objects.
 In keeping with the Catalyst (and Perl) spirit of flexibility, there are
 many different ways approach advanced CRUD operations in a Catalyst
 environment.  One alternative is to use
-L<Catalyst::Helper::Controller::Scaffold> to instantly construct a set
-of Controller methods and templates for basic CRUD operations.  Although
-a popular subject in Quicktime movies that serve as promotional material
-for various frameworks, more real-world applications require more
-control.  Other options include L<Data::FormValidator> and
-L<HTML::FillInForm>.
-
-Here, we will make use of the L<HTML::Widget> to not only ease form
-creation, but to also provide validation of the submitted data.  The
-approached used by the part of the tutorial is to slowly incorporate
-additional L<HTML::Widget> functionality in a step-wise fashion (we
-start with fairly simple form creation and then move on to more complex
-and "magical" features such as validation and
+L<Catalyst::Helper::Controller::Scaffold|Catalyst::Helper::Controller::Scaffold> 
+to instantly construct a set of Controller methods and templates for 
+basic CRUD operations.  Although a popular subject in Quicktime 
+movies that serve as promotional material for various frameworks, 
+real-world applications generally require more control.  Other 
+options include L<Data::FormValidator|Data::FormValidator> and
+L<HTML::FillInForm|HTML::FillInForm>.
+
+Here, we will make use of the L<HTML::Widget|HTML::Widget> to not only 
+ease form creation, but to also provide validation of the submitted 
+data.  The approached used by the part of the tutorial is to slowly 
+incorporate additional L<HTML::Widget|HTML::Widget> functionality in a 
+step-wise fashion (we start with fairly simple form creation and then 
+move on to more complex and "magical" features such as validation and 
 auto-population/auto-saving).
 
 B<Note:> Part 8 of the tutorial is optional.  Users who do not wish to
-use L<HTML::Widget|HTML::Widget> may skip this section.
+use L<HTML::Widget|HTML::Widget> may skip this part.
 
 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
@@ -87,7 +88,7 @@ following command:
 
 =head1 C<HTML::WIDGET> FORM CREATION
 
-This section looks at how L<HTML::Widget> can be used to
+This section looks at how L<HTML::Widget|HTML::Widget> can be used to
 add additional functionality to the manually created form from Part 3.
 
 =head2 Add the C<HTML::Widget> Plugin
@@ -110,7 +111,7 @@ following method:
     
     sub make_book_widget {
         my ($self, $c) = @_;
-
+    
         # Create an HTML::Widget to build the form
         my $w = $c->widget('book_form')->method('post');
     
@@ -125,7 +126,7 @@ following method:
         $w->element('Select',    'authors')->label('Authors')
             ->options(@authors);
         $w->element('Submit',    'submit' )->value('submit');
-
+    
         # Return the widget    
         return $w;
     }
@@ -237,7 +238,8 @@ in the CSS from a single location.
 
 =head2 Create a Template Page To Display The Form
 
-C<root/src/books/hw_form.tt2>
+Open C<root/src/books/hw_form.tt2> in your editor and enter the following:
+
     [% META title = 'Create/Update Book' %]
     
     [% widget_result.as_xml %]
@@ -302,7 +304,7 @@ been marked with a C<*** NEW:> comment):
 
     sub make_book_widget {
         my ($self, $c) = @_;
-
+    
         # Create an HTML::Widget to build the form
         my $w = $c->widget('book_form')->method('post');
             
@@ -310,7 +312,7 @@ been marked with a C<*** NEW:> comment):
         my @authorObjs = $c->model("MyAppDB::Author")->all();
         my @authors = map {$_->id => $_->last_name }
                            sort {$a->last_name cmp $b->last_name} @authorObjs;
-   
+    
         # Create the form feilds
         $w->element('Textfield', 'title'  )->label('Title')->size(60);
         $w->element('Textfield', 'rating' )->label('Rating')->size(1);
@@ -559,7 +561,9 @@ between tables.
 
 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 Catlayst 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/>).
index 0c8e2b3..d5401f8 100644 (file)
@@ -414,7 +414,13 @@ you could have a C<User> controller with both C<login> and C<logout>
 actions.  Remember, Catalyst is designed to be very flexible, and leaves
 such matters up to you, the designer and programmer.
 
-Then open C<lib/MyApp/Controller/Login.pm> and add:
+Then open C<lib/MyApp/Controller/Login.pm>, locate the C<sub index : 
+Private> method (this was automatically inserted by the helpers when we 
+created the Login controller above), and delete this line:
+
+    $c->response->body('Matched MyApp::Controller::Login in Login.');
+
+Then update it to match:
 
     =head2 base
     
@@ -422,7 +428,7 @@ Then open C<lib/MyApp/Controller/Login.pm> and add:
     
     =cut
     
-    sub base :Path :Args(0) {
+    sub index : Private {
         my ($self, $c) = @_;
     
         # Get the username and password from form
@@ -453,20 +459,24 @@ at the login page but receive an error message.  If the C<username> and
 C<password> values are not present in the form, the user will be taken
 to the empty login form.
 
-We are using C<sub base :Path :Args(0) {...}> here to specifically match 
-the URL C</login>.  C<Path> actions (aka, "literal actions") create URI 
-matches relative to the namespace of the controller where they are defined.  
-Although C<Path> supports arguments that allow relative and absolute paths 
-to be defined, here we use an empty C<Path> definition to match on just the 
-name of the controller itself.  The method name, C<base>, is arbitrary.  
-We make the match even more specific with the C<:Args(0)> action modifier 
--- this forces the match on I<only> C</login>, not C</login/somethingelse>.
-
 Note that we could have used something like C<sub default :Private>; 
 however, the use of C<default> actions is discouraged because it does
 not receive path args as with other actions.  The recommended practice 
 is to only use C<default> in C<MyApp::Controller::Root>.
 
+Another options would be to use something like 
+C<sub base :Path :Args(0) {...}> (where the C<...> refers to the login 
+code shown in C<sub index : Private> above). We are using C<sub base 
+:Path :Args(0) {...}> here to specifically match the URL C</login>. 
+C<Path> actions (aka, "literal actions") create URI matches relative to 
+the namespace of the controller where they are defined.  Although 
+C<Path> supports arguments that allow relative and absolute paths to be 
+defined, here we use an empty C<Path> definition to match on just the 
+name of the controller itself.  The method name, C<base>, is arbitrary. 
+We make the match even more specific with the C<:Args(0)> action 
+modifier -- this forces the match on I<only> C</login>, not 
+C</login/somethingelse>.
+
 Next, create a corresponding method in C<lib/MyApp/Controller/Logout.pm>:
 
     =head2 base
@@ -475,7 +485,7 @@ Next, create a corresponding method in C<lib/MyApp/Controller/Logout.pm>:
     
     =cut
     
-    sub base :Path :Args(0) {
+    sub index : Private {
         my ($self, $c) = @_;
     
         # Clear the user's state
@@ -485,8 +495,9 @@ Next, create a corresponding method in C<lib/MyApp/Controller/Logout.pm>:
         $c->response->redirect($c->uri_for('/'));
     }
 
-Note that we are using the same C<sub base :Path :Args(0) {...}> style
-of action as with the login logic.
+As with the login controller, be sure to delete the 
+C<$c->response->body('Matched MyApp::Controller::Logout in Logout.');>
+line of the C<sub index>.
 
 
 =head2 Add a Login Form TT Template Page
@@ -654,11 +665,11 @@ bottom:
       <a href="[% Catalyst.uri_for('form_create') %]">Create</a>
     </p>
 
-Reload your browser and you should now see a "Login" and "Create" links
-at the bottom of the page (as mentioned earlier, you can update 
-template files without reloading the development server).  Click this 
-link to return to the login page.  This time you I<should> see the 
-"You are already logged in" message.
+Reload your browser and you should now see a "Login" and "Create" links 
+at the bottom of the page (as mentioned earlier, you can update template 
+files without reloading the development server).  Click the first link 
+to return to the login page.  This time you I<should> see the "You are 
+already logged in" message.
 
 Finally, click the C<You can logout here> link on the C</login> page.
 You should stay at the login page, but the message should change to "You
@@ -764,6 +775,15 @@ You should now be able to go to L<http://localhost:3000/books/list> and
 login as before.  When done, click the "Logout" link on the login page
 (or point your browser at L<http://localhost:3000/logout>).
 
+B<Note:> If you receive the debug screen in your browser with a 
+C<Can't call method "stash" on an undefined value...> error message,
+make sure that you are using v0.07 of 
+L<Catalyst::Plugin::Authorization::ACL|Catalyst::Plugin::Authorization::ACL>.
+The following command can be a useful way to quickly dump the version number
+of this module on your system:
+
+    perl -MCatalyst::Plugin::Authorization::ACL -e 'print $Catalyst::Plugin::Authorization::ACL::VERSION, "\n";'
+
 
 =head1 AUTHOR
 
index d4b64d5..6cc218b 100644 (file)
@@ -155,13 +155,13 @@ editor and enter the following:
     # all tests. Better to replace "'no_plan'" with "tests => 30" so it
     # knows exactly how many tests need to be run (and will tell you if
     # not), but 'no_plan' is nice for quick & dirty tests
-
+    
     use Test::More 'no_plan';
     
     # Need to specify the name of your app as arg on next line
     # Can also do:
     #   use Test::WWW::Mechanize::Catalyst "MyApp";
-
+    
     use ok "Test::WWW::Mechanize::Catalyst" => "MyApp";
         
     # Create two 'user agents' to simulate two different users ('test01' & 'test02')
@@ -218,7 +218,8 @@ editor and enter the following:
     $ua1->get_ok("http://localhost/books/url_create/TestTitle/2/4",
         "'test01' formless create");
     $ua1->title_is("Book Created", "Book created title");
-    $ua1->content_contains("Added book 'TestTitle' by 'Stevens'", "Check added OK");
+    $ua1->content_contains("Added book 'TestTitle'", "Check title added OK");
+    $ua1->content_contains("by 'Stevens'", "Check author added OK");
     $ua1->content_contains("a rating of 2.", "Check rating added");
     
     # Make sure the new book shows in the list