@@ -1,5 +1,21 @@
Revision history for Catalyst-Manual
+5.8008 2 Aug 2011
+ - Tutorial chaper 3
+ - Remove note about hacking tests to require MyApp so that MyApp->path_to
+ works. Application components should compile independently, and
+ therefore explain this and show configuring components from the
+ app class.
+
+ - Tutorial appendix
+ - Fix confusing mix of singular and plural table names in the MySQL
+ section to be plural, as per the rest of the tutorial.
+
+ - Cookbook
+ - Remove suggestion to generate RSS feeds using Template Toolkit.
+ This is a horrible idea, and it's very very easy to generate an
+ invalid feed.
+
5.8007 29 Feb 2011
- Tutorial
- Switch to use of DBIx::Class::PassphraseColumn for hashed & salted
@@ -9,7 +9,7 @@ build_requires:
configure_requires:
ExtUtils::MakeMaker: 6.42
distribution_type: module
-generated_by: 'Module::Install version 0.990'
+generated_by: 'Module::Install version 1.01'
license: perl
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -19,9 +19,7 @@ no_index:
directory:
- inc
- t
-requires:
- Test::More: 0
resources:
license: http://dev.perl.org/licenses/
repository: http://dev.catalyst.perl.org/repos/Catalyst/Catalyst-Manual/5.80/trunk/
-version: 5.8007
+version: 5.8008
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '0.99';
+ $VERSION = '1.01';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -48,6 +48,14 @@ sub auto_install {
while (my ($mod, $ver) = splice(@requires, 0, 2)) {
$seen{$mod}{$ver}++;
}
+ my @build_requires = map @$_, map @$_, grep ref, $self->build_requires;
+ while (my ($mod, $ver) = splice(@build_requires, 0, 2)) {
+ $seen{$mod}{$ver}++;
+ }
+ my @configure_requires = map @$_, map @$_, grep ref, $self->configure_requires;
+ while (my ($mod, $ver) = splice(@configure_requires, 0, 2)) {
+ $seen{$mod}{$ver}++;
+ }
my @deduped;
while (my ($mod, $ver) = splice(@features_require, 0, 2)) {
@@ -4,7 +4,7 @@ package Module::Install::Base;
use strict 'vars';
use vars qw{$VERSION};
BEGIN {
- $VERSION = '0.99';
+ $VERSION = '1.01';
}
# Suspend handler for "redefined" warnings
@@ -9,7 +9,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '0.99';
+ $VERSION = '1.01';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '0.99';
+ $VERSION = '1.01';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '0.99';
+ $VERSION = '1.01';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -8,7 +8,7 @@ use Fcntl qw/:flock :seek/;
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '0.99';
+ $VERSION = '1.01';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '0.99';
+ $VERSION = '1.01';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -515,6 +515,7 @@ sub __extract_license {
'GNU Free Documentation license' => 'unrestricted', 1,
'GNU Affero General Public License' => 'open_source', 1,
'(?:Free)?BSD license' => 'bsd', 1,
+ 'Artistic license 2\.0' => 'artistic_2', 1,
'Artistic license' => 'artistic', 1,
'Apache (?:Software )?license' => 'apache', 1,
'GPL' => 'gpl', 1,
@@ -550,9 +551,9 @@ sub license_from {
sub _extract_bugtracker {
my @links = $_[0] =~ m#L<(
- \Qhttp://rt.cpan.org/\E[^>]+|
- \Qhttp://github.com/\E[\w_]+/[\w_]+/issues|
- \Qhttp://code.google.com/p/\E[\w_\-]+/issues/list
+ https?\Q://rt.cpan.org/\E[^>]+|
+ https?\Q://github.com/\E[\w_]+/[\w_]+/issues|
+ https?\Q://code.google.com/p/\E[\w_\-]+/issues/list
)>#gx;
my %links;
@links{@links}=();
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '0.99';
+ $VERSION = '1.01';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '0.99';
+ $VERSION = '1.01';
@ISA = qw{Module::Install::Base};
$ISCORE = 1;
}
@@ -31,7 +31,7 @@ BEGIN {
# This is not enforced yet, but will be some time in the next few
# releases once we can make sure it won't clash with custom
# Module::Install extensions.
- $VERSION = '0.99';
+ $VERSION = '1.01';
# Storage for the pseudo-singleton
$MAIN = undef;
@@ -230,8 +230,12 @@ sub preload {
sub new {
my ($class, %args) = @_;
- delete $INC{'FindBin.pm'};
- require FindBin;
+ delete $INC{'FindBin.pm'};
+ {
+ # to suppress the redefine warning
+ local $SIG{__WARN__} = sub {};
+ require FindBin;
+ }
# ignore the prefix on extension modules built from top level.
my $base_path = Cwd::abs_path($FindBin::Bin);
@@ -463,4 +467,4 @@ sub _CLASS ($) {
1;
-# Copyright 2008 - 2010 Adam Kennedy.
+# Copyright 2008 - 2011 Adam Kennedy.
@@ -572,7 +572,7 @@ root of your app (but not in any other controller).
=head1 Models
-Models are where application data belongs. Catalyst is exteremely
+Models are where application data belongs. Catalyst is extremely
flexible with the kind of models that it can use. The recipes here
are just the start.
@@ -961,47 +961,13 @@ L<http://search.cpan.org/perldoc?Template>
=head2 Adding RSS feeds
Adding RSS feeds to your Catalyst applications is simple. We'll see two
-different aproaches here, but the basic premise is that you forward to
+different approaches here, but the basic premise is that you forward to
the normal view action first to get the objects, then handle the output
differently.
-=head3 Using TT templates
-
-This is the aproach used in Agave (L<http://dev.rawmode.org/>).
-
- sub rss : Local {
- my ($self,$c) = @_;
- $c->forward('view');
- $c->stash->{template}='rss.tt';
- }
-
-Then you need a template. Here's the one from Agave:
-
- <?xml version="1.0" encoding="UTF-8"?>
- <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
- <channel>
- <title>[ [% blog.name || c.config.name || "Agave" %] ] RSS Feed</title>
- <link>[% base %]</link>
- <description>Recent posts</description>
- <language>en-us</language>
- <ttl>40</ttl>
- [% WHILE (post = posts.next) %]
- <item>
- <title>[% post.title %]</title>
- <description>[% post.formatted_teaser|html%]</description>
- <pubDate>[% post.pub_date %]</pubDate>
- <guid>[% post.full_uri %]</guid>
- <link>[% post.full_uri %]</link>
- <dc:creator>[% post.author.screenname %]</dc:creator>
- </item>
- [% END %]
- </channel>
- </rss>
-
=head3 Using XML::Feed
-A more robust solution is to use L<XML::Feed>, as was done in the Catalyst
-Advent Calendar. Assuming we have a C<view> action that populates
+Assuming we have a C<view> action that populates
'entries' with some DBIx::Class iterator, the code would look something
like this:
@@ -1025,10 +991,10 @@ like this:
$c->res->body( $feed->as_xml );
}
-A little more code in the controller, but with this approach you're
+With this approach you're
pretty sure to get something that validates.
-Note that for both of the above aproaches, you'll need to set the
+Note that for both of the above approaches, you'll need to set the
content type like this:
$c->res->content_type('application/rss+xml');
@@ -1369,7 +1335,7 @@ even though there are two different methods of looking up a track.
This technique can be expanded as needed to fulfil your requirements - for example,
if you inherit the first action of a chain from a base class, then mixing in a
-different base class can be used to duplicate an entire URL hieratchy at a different
+different base class can be used to duplicate an entire URL hierarchy at a different
point within your application.
=head2 Component-based Subrequests
@@ -1565,7 +1531,7 @@ the same Apache instance because the namespaces will collide.
=head4 Cannot run different versions of libraries.
-If you have two differnet applications which run on the same machine,
+If you have two different applications which run on the same machine,
which need two different versions of a library then the only way to do
this is to have per-vhost perl interpreters (with different library paths).
This is entirely possible, but nullifies all the memory sharing benefits that
@@ -17,7 +17,7 @@ or how best to go about their first CPAN extension module....
=head2 Discussing proposed bugfixes or improvements
-L<http://dev.catalystframework.org/wiki/#Community> has information about how
+L<http://wiki.catalystframework.org/wiki/#Community> has information about how
to get in touch with the Catalyst "community". In particular, you would
want to discuss a proposed change on the mailing list:
@@ -26,24 +26,24 @@ want to discuss a proposed change on the mailing list:
or on IRC:
irc://irc.perl.org/catalyst-dev
- http://dev.catalystframework.org/wiki/livegroups
+ http://wiki.catalystframework.org/wiki/livegroups
Usually, the core team will be more than happy for you to contribute, and
will talk you through how to submit a patch, or get a "commit bit".
=head2 Repositories
-The Catalyst subversion repository can be found at:
-
- svn: http://dev.catalyst.perl.org/repos/Catalyst
- browser: http://dev.catalyst.perl.org/svnweb/Catalyst
-
-and the git repository can be found at:
+The Catalyst git repository can be found at:
read: git://git.shadowcat.co.uk/catagits/PROJECTNAME
write: catagits@git.shadowcat.co.uk:PROJECTNAME
browser: https://git.shadowcat.co.uk/gitweb/gitweb.cgi
+The Catalyst subversion repository can be found at:
+
+ svn: http://dev.catalyst.perl.org/repos/Catalyst
+ browser: http://dev.catalyst.perl.org/svnweb/Catalyst
+
=head2 Schedule
There is no dated release cycle for Catalyst. New releases will be made
@@ -53,12 +53,12 @@ significant feature addition, is completed.
=head2 Roadmap for features
The Catalyst Roadmap is kept at
-L<http://dev.catalyst.perl.org/repos/Catalyst/Catalyst-Runtime/5.80/trunk/lib/Roadmap.pod>
+L<http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits/Catalyst-Runtime.git;a=blob_plain;f=lib/Catalyst/ROADMAP.pod;hb=master>
=head2 Bug list
The TODO list with known bugs / deficiences is kept at
-L<http://dev.catalyst.perl.org/repos/Catalyst/Catalyst-Runtime/5.80/trunk/TODO>
+L<http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits/Catalyst-Runtime.git;a=blob_plain;f=TODO;hb=master>
=head1 The Catalyst Core Team
@@ -121,9 +121,9 @@ current members.
Any change to the Catalyst core which can not be conceived as a
correction of an error in the current feature set will need to be
accepted by at least 3 members of the Core Team before it can be
-committed to the trunk (which is the basis for CPAN releases). Anyone
+committed to master (which is the basis for CPAN releases). Anyone
with access is at any time free to make a branch to develop a proof of
-concept for a feature to be committed to trunk.
+concept for a feature to be committed to master.
=head2 Organizational and Philosophical Decisions.
@@ -127,7 +127,7 @@ for more information about roles in general.
=head2 Inheritance and overriding methods
-When overriding a method, keep in mind that some day additionall
+When overriding a method, keep in mind that some day additional
arguments may be provided to the method, if the last parameter is not
a flat list. It is thus better to override a method by shifting the
invocant off of C<@_> and assign the rest of the used arguments, so
@@ -104,7 +104,7 @@ example:
Now http://localhost:3000/hello prints "Hello World!".
-Note that actions with the C< :Global > attribute are equivalent to
+Note that actions with the C< :Local > attribute are equivalent to
using a C<:Path('action_name') > attribute, so our action could be
equivalently:
@@ -145,7 +145,7 @@ The C<-d> option to C<script/myapp_server.pl>
=item *
The C<CATALYST_DEBUG=1> environment variable (or set it to
-zero to templorarily disable debug output).
+zero to temporarily disable debug output).
=back
@@ -449,30 +449,61 @@ initially demonstrate the concepts, but quickly migrate to a more typical
"wrapper page" type of configuration (where the "wrapper" controls the overall
"look and feel" of your site from a single file or set of files).
-Edit C<lib/MyApp/View/HTML.pm> and you should see that the default
-contents contains something similar to the following:
+Edit C<lib/MyApp/View/HTML.pm> and you should see
+something similar to the following:
- __PACKAGE__->config(TEMPLATE_EXTENSION => '.tt');
+ __PACKAGE__->config(
+ TEMPLATE_EXTENSION => '.tt',
+ render_die => 1,
+ );
And update it to match:
__PACKAGE__->config(
# Change default TT extension
TEMPLATE_EXTENSION => '.tt2',
- # Set the location for TT files
- INCLUDE_PATH => [
- MyApp->path_to( 'root', 'src' ),
+ render_die => 1,
+ );
+
+This changes the default extension for Template Toolkit from '.tt' to
+'.tt2'.
+
+You can also configure components in your application class. For example,
+Edit C<lib/MyApp.pm> and you should see that the default:
+
+ __PACKAGE__->setup;
+
+Above this, add config:
+
+ __PACKAGE__->config(
+ 'View::HTML' => {
+ #Set the location for TT files
+ INCLUDE_PATH => [
+ __PACKAGE__->path_to( 'root', 'src' ),
],
+ },
);
+ # This line was here already
+ __PACKAGE__->setup;
-B<NOTE:> Make sure to add a comma after '.tt2' outside the single
-quote.
+This changes the base directory for your template files from
+C<root> to C<root/src>.
-This changes the default extension for Template Toolkit from '.tt' to
-'.tt2' and changes the base directory for your template files from
-C<root> to C<root/src>. Stick with these conventions for the
-tutorial, but feel free to use whatever options you desire in your
-applications (as with most things Perl, there's more than one way to
+The reason to do this outside the C<lib/MyApp/View/HTML.pm> file
+is that the template path is found with the C<path_to> method,
+to get a path relative to the application root (no matter where it
+is installed), but this requires the application to be loaded...
+
+Trying to set this setting in the view means that you have a chicken
+and egg problem, in that the view requires the application to be loaded,
+but loading the application loads the view.
+
+Putting the configuration which depends on the application class into
+that class is the neatest way to avoid this issue.
+
+Please stick with the settings above for the duration of the
+tutorial, but feel free to use whatever options you desire in your
+applications (as with most things Perl, there's more than one way to
do it...).
B<Note:> We will use C<root/src> as the base directory for our
@@ -481,7 +512,6 @@ C<root/src/_controller_name_/_action_name_.tt2>. Another popular option is to
use C<root/> as the base (with a full filename pattern of
C<root/_controller_name_/_action_name_.tt2>).
-
=head2 Create a TT Template Page
First create a directory for book-related TT templates:
@@ -1021,7 +1051,7 @@ edit many individual files.
In order to create a wrapper, you must first edit your TT view and
tell it where to find your wrapper file.
-Edit you TT view in C<lib/MyApp/View/HTML.pm> and change it to match the
+Edit your TT view in C<lib/MyApp/View/HTML.pm> and change it to match the
following:
__PACKAGE__->config(
@@ -1287,14 +1317,15 @@ L<DBIx::Class::Relationship/belongs_to> for the details.
Although recent versions of SQLite and L<DBIx::Class::Schema::Loader>
automatically handle the C<has_many> and C<belongs_to> relationships,
-C<many_to_many> relationships currently need to be manually inserted.
-To add a C<many_to_many> relationship, first edit
+C<many_to_many> relationship bridges (not technically a relationship)
+currently need to be manually inserted.
+To add a C<many_to_many> relationship bridge, first edit
C<lib/MyApp/Schema/Result/Book.pm> and add the following text below
the C<# You can replace this text...> comment:
# many_to_many():
# args:
- # 1) Name of relationship, DBIC will create accessor with this name
+ # 1) Name of relationship bridge, DBIC will create accessor with this name
# 2) Name of has_many() relationship this many_to_many() is shortcut for
# 3) Name of belongs_to() relationship in model class of has_many() above
# You must already have the has_many() defined to use a many_to_many().
@@ -1305,7 +1336,7 @@ file. As with any Perl package, we need to end the last line with
a statement that evaluates to C<true>. This is customarily done with
C<1;> on a line by itself.
-The C<many_to_many> relationship is optional, but it makes it
+The C<many_to_many> relationship bridge is optional, but it makes it
easier to map a book to its collection of authors. Without
it, we would have to "walk" through the C<book_author> table as in
C<$book-E<gt>book_author-E<gt>first-E<gt>author-E<gt>last_name> (we
@@ -1314,17 +1345,17 @@ but note that because C<$book-E<gt>book_author> can return multiple
authors, we have to use C<first> to display a single author).
C<many_to_many> allows us to use the shorter
C<$book-E<gt>author-E<gt>first-E<gt>last_name>. Note that you cannot
-define a C<many_to_many> relationship without also having the
+define a C<many_to_many> relationship bridge without also having the
C<has_many> relationship in place.
Then edit C<lib/MyApp/Schema/Result/Author.pm> and add the reverse
-C<many_to_many> relationship for C<Author> as follows (again, be careful
+C<many_to_many> relationship bridge for C<Author> as follows (again, be careful
to put in above the C<1;> but below the C<# DO NOT MODIFY THIS OR
ANYTHING ABOVE!> comment):
# many_to_many():
# args:
- # 1) Name of relationship, DBIC will create accessor with this name
+ # 1) Name of relationship bridge, DBIC will create accessor with this name
# 2) Name of has_many() relationship this many_to_many() is shortcut for
# 3) Name of belongs_to() relationship in model class of has_many() above
# You must already have the has_many() defined to use a many_to_many().
@@ -846,14 +846,14 @@ C<__PACKAGE__-E<gt>config> setting to something like:
name => 'MyApp',
# Disable deprecated behavior needed by old applications
disable_component_resolution_regex_fallback => 1,
- session => { flash_to_stash => 1 },
+ 'Plugin::Session' => { flash_to_stash => 1 },
);
B<or> add the following to C<myapp.conf>:
- <session>
+ <Plugin::Session>
flash_to_stash 1
- </session>
+ </Plugin::Session>
The C<__PACKAGE__-E<gt>config> option is probably preferable here
since it's not something you will want to change at runtime without it
@@ -92,7 +92,7 @@ add additional functionality to the manually created form from Chapter 4.
=head2 Using FormHandler in your controllers
-FormHandler dosen't have a Catalyst base controller, because interfacing
+FormHandler doesn't have a Catalyst base controller, because interfacing
to a form is only a couple of lines of code.
=head2 Create a Book Form
@@ -561,10 +561,10 @@ in you MySQL. You can simply figure out that your install supports it or not:
# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
-
+
Type 'help;' or '\h' for help. Type '\c' to clear the current input
statement.
-
+
mysql> SHOW VARIABLES LIKE 'have_innodb';
+---------------+-------+
| Variable_name | Value |
@@ -572,7 +572,7 @@ in you MySQL. You can simply figure out that your install supports it or not:
| have_innodb | YES |
+---------------+-------+
1 row in set (0.01 sec)
-
+
mysql> exit
Bye
@@ -586,21 +586,21 @@ Create the database and set the permissions:
# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
-
+
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
-
+
mysql> CREATE DATABASE `myapp`;
Query OK, 1 row affected (0.01 sec)
-
+
mysql> GRANT ALL PRIVILEGES ON myapp.* TO 'tutorial'@'localhost' IDENTIFIED BY 'yourpassword';
Query OK, 0 rows affected (0.00 sec)
-
+
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
-
+
mysql> exit
Bye
-
+
=item *
@@ -615,20 +615,20 @@ Open the C<myapp01_mysql.sql> in your editor and enter:
--
-- Create a very simple database to hold book and author information
--
- CREATE TABLE IF NOT EXISTS `book` (
+ CREATE TABLE IF NOT EXISTS `books` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` text CHARACTER SET utf8,
`rating` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 'book_authors' is a many-to-many join table between books & authors
- CREATE TABLE IF NOT EXISTS `book_author` (
+ CREATE TABLE IF NOT EXISTS `book_authors` (
`book_id` int(11) NOT NULL DEFAULT '0',
`author_id` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`book_id`,`author_id`),
KEY `author_id` (`author_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- CREATE TABLE IF NOT EXISTS `author` (
+ CREATE TABLE IF NOT EXISTS `authors` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`first_name` text CHARACTER SET utf8,
`last_name` text CHARACTER SET utf8,
@@ -637,14 +637,14 @@ Open the C<myapp01_mysql.sql> in your editor and enter:
---
--- Load some sample data
---
- INSERT INTO `book` (`id`, `title`, `rating`) VALUES
+ INSERT INTO `books` (`id`, `title`, `rating`) VALUES
(1, 'CCSP SNRS Exam Certification Guide', 5),
(2, 'TCP/IP Illustrated, Volume 1', 5),
(3, 'Internetworking with TCP/IP Vol.1', 4),
(4, 'Perl Cookbook', 5),
(5, 'Designing with Web Standards', 5);
-
- INSERT INTO `book_author` (`book_id`, `author_id`) VALUES
+
+ INSERT INTO `book_authors` (`book_id`, `author_id`) VALUES
(1, 1),
(1, 2),
(1, 3),
@@ -653,8 +653,8 @@ Open the C<myapp01_mysql.sql> in your editor and enter:
(4, 6),
(4, 7),
(5, 8);
-
- INSERT INTO `author` (`id`, `first_name`, `last_name`) VALUES
+
+ INSERT INTO `authors` (`id`, `first_name`, `last_name`) VALUES
(1, 'Greg', 'Bastien'),
(2, 'Sara', 'Nasseh'),
(3, 'Christian', 'Degu'),
@@ -663,10 +663,10 @@ Open the C<myapp01_mysql.sql> in your editor and enter:
(6, 'Tom', 'Christiansen'),
(7, 'Nathan', 'Torkington'),
(8, 'Jeffrey', 'Zeldman');
-
- ALTER TABLE `book_author`
- ADD CONSTRAINT `book_author_ibfk_2` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
- ADD CONSTRAINT `book_author_ibfk_1` FOREIGN KEY (`book_id`) REFERENCES `book` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
+
+ ALTER TABLE `book_authors`
+ ADD CONSTRAINT `book_author_ibfk_2` FOREIGN KEY (`author_id`) REFERENCES `authors` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ ADD CONSTRAINT `book_author_ibfk_1` FOREIGN KEY (`book_id`) REFERENCES `books` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
=item *
@@ -681,11 +681,11 @@ Make sure the data loaded correctly:
$ mysql -u tutorial -p myapp
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
-
+
Welcome to the MySQL monitor. Commands end with ; or \g.
-
+
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
-
+
mysql> show tables;
+-----------------+
| Tables_in_myapp |
@@ -695,7 +695,7 @@ Make sure the data loaded correctly:
| books |
+-----------------+
3 rows in set (0.00 sec)
-
+
mysql> select * from books;
+----+------------------------------------+--------+
| id | title | rating |
@@ -707,7 +707,7 @@ Make sure the data loaded correctly:
| 5 | Designing with Web Standards | 5 |
+----+------------------------------------+--------+
5 rows in set (0.00 sec)
-
+
mysql>
=back
@@ -750,12 +750,12 @@ Open C<myapp02_mysql.sql> in your editor and enter:
--
-- Add users and roles tables, along with a many-to-many join table
--
- CREATE TABLE IF NOT EXISTS `role` (
+ CREATE TABLE IF NOT EXISTS `roles` (
`id` int(11) NOT NULL,
`role` text CHARACTER SET utf8,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- CREATE TABLE IF NOT EXISTS `user` (
+ CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL,
`username` text CHARACTER SET utf8,
`password` text CHARACTER SET utf8,
@@ -765,7 +765,7 @@ Open C<myapp02_mysql.sql> in your editor and enter:
`active` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- CREATE TABLE IF NOT EXISTS `user_role` (
+ CREATE TABLE IF NOT EXISTS `user_roles` (
`user_id` int(11) NOT NULL DEFAULT '0',
`role_id` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`user_id`,`role_id`),
@@ -774,24 +774,24 @@ Open C<myapp02_mysql.sql> in your editor and enter:
--
-- Load up some initial test data
--
- INSERT INTO `role` (`id`, `role`) VALUES
+ INSERT INTO `roles` (`id`, `role`) VALUES
(1, 'user'),
(2, 'admin');
-
- INSERT INTO `user` (`id`, `username`, `password`, `email_address`, `first_name`, `last_name`, `active`) VALUES
+
+ INSERT INTO `users` (`id`, `username`, `password`, `email_address`, `first_name`, `last_name`, `active`) VALUES
(1, 'test01', 'mypass', 't01@na.com', 'Joe', 'Blow', 1),
(2, 'test02', 'mypass', 't02@na.com', 'Jane', 'Doe', 1),
(3, 'test03', 'mypass', 't03@na.com', 'No', 'Go', 0);
-
- INSERT INTO `user_role` (`user_id`, `role_id`) VALUES
+
+ INSERT INTO `user_roles` (`user_id`, `role_id`) VALUES
(1, 1),
(2, 1),
(3, 1),
(1, 2);
-
- ALTER TABLE `user_role`
- ADD CONSTRAINT `user_role_ibfk_2` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
- ADD CONSTRAINT `user_role_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
+
+ ALTER TABLE `user_roles
+ ADD CONSTRAINT `user_role_ibfk_2` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ ADD CONSTRAINT `user_role_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
=item *
@@ -6,7 +6,7 @@ package Catalyst::Manual;
use strict;
use warnings;
-our $VERSION = '5.8007';
+our $VERSION = '5.8008';
=head1 NAME