capabilities, including full Update functionality, will be addressed in
Part 9.
+Although this part of the tutorial will show you how to build CRUD
+functionality yourself, another option is to use a "CRUD builder" type
+of tool to automate the process. You get less control, but it's quick
+and easy. For example, see
+L<CatalystX::ListFramework::Builder|CatalystX::ListFramework::Builder>,
+L<CatalystX::CRUD|CatalystX::CRUD>, and
+L<CatalystX::CRUD::YUI|CatalystX::CRUD::YUI>.
+
You can checkout the source code for this example from the catalyst
subversion repository as per the instructions in
-L<Catalyst::Manual::Tutorial::Intro>
+L<Catalyst::Manual::Tutorial::Intro|Catalyst::Manual::Tutorial::Intro>.
=head1 FORMLESS SUBMISSION
# 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::Books')->create({
+ my $book = $c->model('DB::Books')->create({
title => $title,
rating => $rating
});
[% # 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>
+ <p><a href="[% c.uri_for('/books/list') %]">Return to list</a></p>
[% # Try out the TT Dumper (for development only!) -%]
<pre>
[% Dumper.dump(book) %]
</pre>
-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 3.
+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|Data::Dumper> "pretty printing" of objects and
+variables. Other than that, the rest of the code should be familiar
+from the examples in Part 3.
-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:
- $ script/myapp_server.pl
+ $ DBIC_TRACE=1 script/myapp_server.pl
Note that new path for C</books/url_create> appears in the startup debug
output.
the existing record for Richard Stevens. The C<SELECT> statement results
from DBIC automatically fetching the book for the C<Dumper.dump(book)>.
-If you then click the "Return to list" link, you should find that there
-are now six books shown (if necessary, Shift-Reload your browser at the
-C</books/list> page).
+If you then click the "Return to list" link, you should find that
+there are now six books shown (if necessary, Shift+Reload or
+Ctrl+Reload your browser at the C</books/list> page).
Then I<add 2 more copies of the same book> so that we have some extras for
our delete logic that will be coming up soon. Enter the same URL above
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 = 'Manual Form Book Create' -%]
- <form method="post" action="[% Catalyst.uri_for('form_create_do') %]">
+ <form method="post" action="[% c.uri_for('form_create_do') %]">
<table>
<tr><td>Title:</td><td><input type="text" name="title"></td></tr>
<tr><td>Rating:</td><td><input type="text" name="rating"></td></tr>
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 a Method to Process Form Values and Update Database
Edit C<lib/MyApp/Controller/Books.pm> and add the following method to
my $author_id = $c->request->params->{author_id} || '1';
# Create the book
- my $book = $c->model('MyAppDB::Books')->create({
+ my $book = $c->model('DB::Books')->create({
title => $title,
rating => $rating,
});
Point your browser to L<http://localhost:3000/books/form_create> and
enter "TCP/IP Illustrated, Vol 3" for the title, a rating of 5, and an
-author ID of 4. You should then be forwarded to the same
+author ID of 4. You should then see the output of the same
C<create_done.tt2> template seen in earlier examples. Finally, click
"Return to list" to view the full list of books.
</td>
<td>
[% # Add a link to delete a book %]
- <a href="[% Catalyst.uri_for('delete/') _ book.id %]">Delete</a>
+ <a href="[% c.uri_for('delete', book.id) %]">Delete</a>
</td>
</tr>
[% END -%]
</table>
-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).
+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).
+
+B<Note:> You should use more than just a simple link with your
+applications. Consider using some sort of of confirmation page
+(typically with unique actions in your controller for both the
+confirmation and the actual delete operation). Also, you should try
+to use an HTTP POST operation (versus the GET used here) for
+operations that change the state of your application (e.g., the
+database).
+
=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
my ($self, $c, $id) = @_;
# Search for the book and then delete it
- $c->model('MyAppDB::Books')->search({id => $id})->delete_all;
+ $c->model('DB::Books')->search({id => $id})->delete_all;
# Set a status message to be displayed at the top of the view
$c->stash->{status_msg} = "Book deleted.";
my ($self, $c, $id) = @_;
# Search for the book and then delete it
- $c->model('MyAppDB::Books')->search({id => $id})->delete_all;
+ $c->model('DB::Books')->search({id => $id})->delete_all;
# Set a status message to be displayed at the top of the view
$c->stash->{status_msg} = "Book deleted.";
my ($self, $c, $id) = @_;
# Search for the book and then delete it
- $c->model('MyAppDB::Books')->search({id => $id})->delete_all;
+ $c->model('DB::Books')->search({id => $id})->delete_all;
# Redirect the user back to the list page with status msg as an arg
$c->response->redirect($c->uri_for('/books/list',
This modification simply leverages the ability of C<uri_for> to include
an arbitrary number of name/value pairs in a hash reference. Next, we
-need to update C<root/lib/site/layout> to handle C<status_msg> as a
+need to update C<root/src/wrapper> to handle C<status_msg> as a
query parameter:
- <div id="header">[% PROCESS site/header %]</div>
-
+ ...
<div id="content">
- <span class="message">[% status_msg || Catalyst.request.params.status_msg %]</span>
- <span class="error">[% error_msg %]</span>
- [% content %]
- </div>
-
- <div id="footer">[% PROCESS site/footer %]</div>
+ [%# Status and error messages %]
+ <span class="message">[% status_msg || c.request.params.status_msg %]</span>
+ <span class="error">[% error_msg %]</span>
+ [%# This is where TT will stick all of your template's contents. -%]
+ [% content %]
+ </div><!-- end content -->
+ ...
+
+Although the sample above only shows the C<content> div, leave the
+rest of the file intact -- the only change we made to the C<wrapper.tt2>
+was to add "C<|| c.request.params.status_msg>" to the
+C<E<lt>span class="message"E<gt>> line.
=head2 Try the Delete and Redirect With Query Param Logic
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/>.
+L<http://dev.catalyst.perl.org/repos/Catalyst/Catalyst-Manual/5.70/trunk/lib/Catalyst/Manual/Tutorial/>.
-Copyright 2006, Kennedy Clark, under Creative Commons License
-(L<http://creativecommons.org/licenses/by-nc-sa/2.5/>).
+Copyright 2006-2008, Kennedy Clark, under Creative Commons License
+(L<http://creativecommons.org/licenses/by-sa/3.0/us/>).