Suggestion from Stefan Kangas about "un-indenting" code in Emacs (thanks, Stefan)
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / Tutorial / Appendices.pod
1 =head1 NAME
2
3 Catalyst::Manual::Tutorial::Appendices - Catalyst Tutorial - Chapter 10: Appendices
4
5
6 =head1 OVERVIEW
7
8 This is B<Chapter 10 of 10> for the Catalyst tutorial.
9
10 L<Tutorial Overview|Catalyst::Manual::Tutorial>
11
12 =over 4
13
14 =item 1
15
16 L<Introduction|Catalyst::Manual::Tutorial::Intro>
17
18 =item 2
19
20 L<Catalyst Basics|Catalyst::Manual::Tutorial::CatalystBasics>
21
22 =item 3
23
24 L<More Catalyst Basics|Catalyst::Manual::Tutorial::MoreCatalystBasics>
25
26 =item 4
27
28 L<Basic CRUD|Catalyst::Manual::Tutorial::BasicCRUD>
29
30 =item 5
31
32 L<Authentication|Catalyst::Manual::Tutorial::Authentication>
33
34 =item 6
35
36 L<Authorization|Catalyst::Manual::Tutorial::Authorization>
37
38 =item 7
39
40 L<Debugging|Catalyst::Manual::Tutorial::Debugging>
41
42 =item 8
43
44 L<Testing|Catalyst::Manual::Tutorial::Testing>
45
46 =item 9
47
48 L<Advanced CRUD|Catalyst::Manual::Tutorial::AdvancedCRUD>
49
50 =item 10
51
52 B<Appendices>
53
54 =back
55
56
57 =head1 DESCRIPTION
58
59 This chapter of the tutorial provides supporting information relevant to
60 the Catalyst tutorial.
61
62
63 =head1 APPENDIX 1: CUT AND PASTE FOR POD-BASED EXAMPLES
64
65 You may notice that Pod indents example code with four spaces.  This
66 section provides some quick advice to "un-indent" this text in common
67 editors.
68
69 =head2 "Un-indenting" with Vi/Vim
70
71 When cutting and pasting multi-line text from Pod-based documents, the
72 following vi/vim regexs can be helpful to "un-indent" the inserted text
73 (do NOT type the quotes, they are only included to show spaces in the
74 regex patterns).  I<Note that all 3 of the regexs end in 4 spaces>:
75
76 =over 4
77
78 =item *
79
80 ":0,$s/^    "
81
82 Removes four leading spaces from the entire file (from the first line,
83 C<0>, to the last line, C<$>).
84
85 =item *
86
87 "%s/^    "
88
89 A shortcut for the previous item (C<%> specifies the entire file; so
90 this removes four leading spaces from every line).
91
92 =item *
93
94 ":.,$s/^    "
95
96 Removes the first four spaces from the line the cursor is on at the time
97 the regex command is executed (".") to the last line of the file.
98
99 =item *
100
101 ":.,44s/^    "
102
103 Removes four leading space from the current line through line 44
104 (obviously adjust the C<44> to the appropriate value in your example).
105
106 =back
107
108 =head2 "Un-indenting" with Emacs
109
110 Although the author has not used Emacs for many years (apologies to
111 the Emacs fans out there), here is a quick hint to get you started.  To
112 replace the leading spaces of every line in a file, use:
113
114     M-x replace-regexp<RET>
115     Replace regexp: ^    <RET>
116     with: <RET>
117
118 All of that will occur on the single line at the bottom of your screen.
119 Note that "<RET>" represents the return key/enter.  Also, there are
120 four spaces after the "^" on the "Replace regexp:" line and no spaces
121 entered on the last line.
122
123 You can limit the replacement operation by selecting text first (depending
124 on your version of Emacs, you can either use the mouse or experiment with
125 commands such as C<C-SPC> to set the mark at the cursor location and
126 C<C-E<lt>> and C<C-E<gt>> to set the mark at the beginning and end of the
127 file respectively.
128
129 Also, Stefan Kangas sent in the following tip about an alternate 
130 approach using the command C<indent-region> to redo the indentation 
131 for the currently selected region (adhering to indent rules in the 
132 current major mode). You can run the command by typing M-x indent-
133 region or pressing the default keybinding C-M-\ in cperl-mode. 
134 Additional details can be found here:
135
136 L<http://www.gnu.org/software/emacs/manual/html_node/emacs/Indentation-Comman>
137
138
139 =head1 APPENDIX 2: USING POSTGRESQL AND MYSQL
140
141 The main database used in this tutorial is the very simple yet powerful
142 SQLite.  This section provides information that can be used to "convert"
143 the tutorial to use PostgreSQL and MySQL.  However, note that part of
144 the beauty of the MVC architecture is that very little database-specific
145 code is spread throughout the system (at least when MVC is "done
146 right").  Consequently, converting from one database to another is
147 relatively painless with most Catalyst applications.  In general, you
148 just need to adapt the schema definition C<.sql> file you use to
149 initialize your database and adjust a few configuration parameters.
150
151 Also note that the purpose of the data definition statements for this
152 section are not designed to take maximum advantage of the various
153 features in each database for issues such as referential integrity and
154 field types/constraints.
155
156
157 =head2 PostgreSQL
158
159 Use the following steps to adapt the tutorial to PostgreSQL.  Thanks 
160 to Caelum (Rafael Kitover) for assistance with the most recent 
161 updates, and Louis Moore, Marcello Romani and Tom Lanyon for help with 
162 earlier versions.
163
164 =over 4
165
166 =item *
167
168 Chapter 3: More Catalyst Basics
169
170 =over 4
171
172 =item *
173
174 Install the PostgreSQL server and client and DBD::Pg:
175
176 If you are following along in Debian 5, you can quickly install these 
177 items via this command:
178
179     sudo aptitude install postgresql libdbd-pg-perl libdatetime-format-pg-perl
180
181 To configure the permissions, you can open 
182 C</etc/postgresql/8.3/main/pg_hba.conf> and change this line (near the 
183 bottom):
184
185     # "local" is for Unix domain socket connections only
186     local   all         all                               ident sameuser
187
188 to:
189
190     # "local" is for Unix domain socket connections only
191     local   all         all                               trust
192
193 And then restart PostgreSQL:
194
195     sudo /etc/init.d/postgresql-8.3 restart
196
197
198 =item *
199
200 Create the database and a user for the database (note that we are 
201 using "E<lt>catalystE<gt>" to represent the hidden password of 
202 "catalyst"):
203
204     $ sudo -u postgres createuser -P catappuser
205     Enter password for new role: <catalyst>
206     Enter it again: <catalyst>
207     Shall the new role be a superuser? (y/n) n
208     Shall the new role be allowed to create databases? (y/n) n
209     Shall the new role be allowed to create more new roles? (y/n) n
210     CREATE ROLE
211     $ sudo -u postgres createdb -O catappuser catappdb
212     CREATE DATABASE
213
214 =item *
215
216 Create the C<.sql> file and load the data:
217
218 =over 4
219
220 =item *
221
222 Open the C<myapp01_psql.sql> in your editor and enter:
223
224     --
225     -- Drops just in case you are reloading
226     ---
227     DROP TABLE IF EXISTS books CASCADE;
228     DROP TABLE IF EXISTS authors CASCADE;
229     DROP TABLE IF EXISTS book_authors CASCADE;
230     DROP TABLE IF EXISTS users CASCADE;
231     DROP TABLE IF EXISTS roles CASCADE;
232     DROP TABLE IF EXISTS user_roles CASCADE;
233     
234     --
235     -- Create a very simple database to hold book and author information
236     --
237     CREATE TABLE books (
238         id          SERIAL PRIMARY KEY,
239         title       TEXT ,
240         rating      INTEGER,
241         -- Manually add these later
242         -- created     TIMESTAMP NOT NULL DEFAULT now(),
243         -- updated     TIMESTAMP
244     );
245     
246     CREATE TABLE authors (
247         id          SERIAL PRIMARY KEY,
248         first_name  TEXT,
249         last_name   TEXT
250     );
251     
252     -- 'book_authors' is a many-to-many join table between books & authors
253     CREATE TABLE book_authors (
254         book_id     INTEGER REFERENCES books(id) ON DELETE CASCADE ON UPDATE CASCADE,
255         author_id   INTEGER REFERENCES authors(id) ON DELETE CASCADE ON UPDATE CASCADE,
256         PRIMARY KEY (book_id, author_id)
257     );
258     
259     ---
260     --- Load some sample data
261     ---
262     INSERT INTO books (title, rating) VALUES ('CCSP SNRS Exam Certification Guide', 5);
263     INSERT INTO books (title, rating) VALUES ('TCP/IP Illustrated, Volume 1', 5);
264     INSERT INTO books (title, rating) VALUES ('Internetworking with TCP/IP Vol.1', 4);
265     INSERT INTO books (title, rating) VALUES ('Perl Cookbook', 5);
266     INSERT INTO books (title, rating) VALUES ('Designing with Web Standards', 5);
267     INSERT INTO authors (first_name, last_name) VALUES ('Greg', 'Bastien');
268     INSERT INTO authors (first_name, last_name) VALUES ('Sara', 'Nasseh');
269     INSERT INTO authors (first_name, last_name) VALUES ('Christian', 'Degu');
270     INSERT INTO authors (first_name, last_name) VALUES ('Richard', 'Stevens');
271     INSERT INTO authors (first_name, last_name) VALUES ('Douglas', 'Comer');
272     INSERT INTO authors (first_name, last_name) VALUES ('Tom', 'Christiansen');
273     INSERT INTO authors (first_name, last_name) VALUES ('Nathan', 'Torkington');
274     INSERT INTO authors (first_name, last_name) VALUES ('Jeffrey', 'Zeldman');
275     INSERT INTO book_authors VALUES (1, 1);
276     INSERT INTO book_authors VALUES (1, 2);
277     INSERT INTO book_authors VALUES (1, 3);
278     INSERT INTO book_authors VALUES (2, 4);
279     INSERT INTO book_authors VALUES (3, 5);
280     INSERT INTO book_authors VALUES (4, 6);
281     INSERT INTO book_authors VALUES (4, 7);
282     INSERT INTO book_authors VALUES (5, 8);
283
284 =item *
285
286 Load the data:
287
288     $ psql -U catappuser -W catappdb -f myapp01_psql.sql
289     Password for user catappuser: 
290     psql:myapp01_psql.sql:8: NOTICE:  CREATE TABLE will create implicit sequence "books_id_seq" for serial column "books.id"
291     psql:myapp01_psql.sql:8: NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "books_pkey" for table "books"
292     CREATE TABLE
293     psql:myapp01_psql.sql:15: NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "book_authors_pkey" for table "book_authors"
294     CREATE TABLE
295     psql:myapp01_psql.sql:21: NOTICE:  CREATE TABLE will create implicit sequence "authors_id_seq" for serial column "authors.id"
296     psql:myapp01_psql.sql:21: NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "authors_pkey" for table "authors"
297     CREATE TABLE
298     INSERT 0 1
299     INSERT 0 1
300     INSERT 0 1
301     ...
302
303 =item *
304
305 Make sure the data loaded correctly:
306
307     $ psql -U catappuser -W catappdb
308     Password for user catappuser: <catalyst>
309     Welcome to psql 8.3.7, the PostgreSQL interactive terminal.
310     
311     Type:  \copyright for distribution terms
312            \h for help with SQL commands
313            \? for help with psql commands
314            \g or terminate with semicolon to execute query
315            \q to quit
316     
317     catappdb=> \dt
318                  List of relations
319      Schema |     Name     | Type  |   Owner    
320     --------+--------------+-------+------------
321      public | authors      | table | catappuser
322      public | book_authors | table | catappuser
323      public | books        | table | catappuser
324     (3 rows)
325     
326     catappdb=> select * from books;
327      id |               title                | rating 
328     ----+------------------------------------+--------
329       1 | CCSP SNRS Exam Certification Guide |      5
330       2 | TCP/IP Illustrated, Volume 1       |      5
331       3 | Internetworking with TCP/IP Vol.1  |      4
332       4 | Perl Cookbook                      |      5
333       5 | Designing with Web Standards       |      5
334     (5 rows)
335     
336     catappdb=> 
337
338 =back
339
340 =item *
341
342 After the steps where you:
343
344     edit lib/MyApp.pm
345     
346     create lib/MyAppDB.pm
347     
348     create lib/MyAppDB/Book.pm
349     
350     create lib/MyAppDB/Author.pm
351     
352     create lib/MyAppDB/BookAuthor.pm
353
354
355 =item *
356
357 Generate the model using the Catalyst "_create.pl" script:
358
359     $ rm lib/MyApp/Model/DB.pm   # Delete just in case already there
360     $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema \
361         create=static components=TimeStamp,EncodedColumn \
362         'dbi:Pg:dbname=catappdb' 'catappuser' 'catalyst' '{ AutoCommit => 1 }'
363
364 =back
365
366 =item *
367
368 Chapter 4: Basic CRUD
369
370 Add Datetime Columns to Our Existing Books Table
371
372     $ psql -U catappuser -W catappdb
373     ...
374     catappdb=> ALTER TABLE books ADD created TIMESTAMP NOT NULL DEFAULT now();
375     ALTER TABLE
376     catappdb=> ALTER TABLE books ADD updated TIMESTAMP;
377     ALTER TABLE
378     catappdb=> \q
379
380 Re-generate the model using the Catalyst "_create.pl" script:
381
382     $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema \
383         create=static components=TimeStamp,EncodedColumn \
384         'dbi:Pg:dbname=catappdb' 'catappuser' 'catalyst' '{ AutoCommit => 1 }'
385
386
387 =item *
388
389 Chapter 5: Authentication
390
391 =over 4
392
393 =item *
394
395 Create the C<.sql> file for the user/roles data:
396
397 Open C<myapp02_psql.sql> in your editor and enter:
398
399     --
400     -- Add users and roles tables, along with a many-to-many join table
401     --
402     
403     CREATE TABLE users (
404         id            SERIAL PRIMARY KEY,
405         username      TEXT,
406         password      TEXT,
407         email_address TEXT,
408         first_name    TEXT,
409         last_name     TEXT,
410         active        INTEGER
411     );
412     
413     CREATE TABLE roles (
414         id   SERIAL PRIMARY KEY,
415         role TEXT
416     );
417     
418     CREATE TABLE user_roles (
419         user_id INTEGER REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE,
420         role_id INTEGER REFERENCES roles(id) ON DELETE CASCADE ON UPDATE CASCADE,
421         PRIMARY KEY (user_id, role_id)
422     );
423     
424     --
425     -- Load up some initial test data
426     --
427     INSERT INTO users (username, password, email_address, first_name, last_name, active) 
428         VALUES ('test01', 'mypass', 't01@na.com', 'Joe',  'Blow', 1);
429     INSERT INTO users (username, password, email_address, first_name, last_name, active) 
430         VALUES ('test02', 'mypass', 't02@na.com', 'Jane', 'Doe',  1);
431     INSERT INTO users (username, password, email_address, first_name, last_name, active)
432         VALUES ('test03', 'mypass', 't03@na.com', 'No',   'Go',   0);
433     INSERT INTO roles (role) VALUES ('user');
434     INSERT INTO roles (role) VALUES ('admin');
435     INSERT INTO user_roles VALUES (1, 1);
436     INSERT INTO user_roles VALUES (1, 2);
437     INSERT INTO user_roles VALUES (2, 1);
438     INSERT INTO user_roles VALUES (3, 1);
439
440 =item *
441
442 Load the data:
443
444     $ psql -U catappuser -W catappdb -f myapp02_psql.sql
445     Password for user catappuser: <catalyst>
446     psql:myapp02_psql.sql:13: NOTICE:  CREATE TABLE will create implicit sequence "users_id_seq" for serial column "users.id"
447     psql:myapp02_psql.sql:13: NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "users_pkey" for table "users"
448     CREATE TABLE
449     psql:myapp02_psql.sql:18: NOTICE:  CREATE TABLE will create implicit sequence "roles_id_seq" for serial column "roles.id"
450     psql:myapp02_psql.sql:18: NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "roles_pkey" for table "roles"
451     CREATE TABLE
452     psql:myapp02_psql.sql:24: NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "user_roles_pkey" for table "user_roles"
453     CREATE TABLE
454     INSERT 0 1
455     INSERT 0 1
456     INSERT 0 1
457     INSERT 0 1
458     INSERT 0 1
459     INSERT 0 1
460     INSERT 0 1
461     INSERT 0 1
462     INSERT 0 1
463
464 Confirm with:
465
466     $ psql -U catappuser -W catappdb -c "select * from users"
467     Password for user catappuser: <catalyst>
468      id | username | password | email_address | first_name | last_name | active 
469     ----+----------+----------+---------------+------------+-----------+--------
470       1 | test01   | mypass   | t01@na.com    | Joe        | Blow      |      1
471       2 | test02   | mypass   | t02@na.com    | Jane       | Doe       |      1
472       3 | test03   | mypass   | t03@na.com    | No         | Go        |      0
473     (3 rows)
474
475
476 =item *
477
478 Modify C<set_hashed_passwords.pl> to match the following (the only difference
479 is the C<connect> line):
480
481     #!/usr/bin/perl
482     
483     use strict;
484     use warnings;
485     
486     use MyApp::Schema;
487     
488     my $schema = MyApp::Schema->connect('dbi:Pg:dbname=catappdb', 'catappuser', 'catalyst');
489     
490     my @users = $schema->resultset('Users')->all;
491     
492     foreach my $user (@users) {
493         $user->password('mypass');
494         $user->update;
495     }
496
497 Run the C<set_hashed_passwords.pl> as per the "normal" flow of the 
498 tutorial:
499
500     $ perl -Ilib set_hashed_passwords.pl
501
502 You can verify that it worked with this command:
503
504     $ psql -U catappuser -W catappdb -c "select * from users"
505
506
507 =back
508
509 =back
510
511
512 =head2 MySQL
513
514 B<NOTE:> This section is out of data with the rest of the tutorial.
515 Consider using SQLite or PostgreSQL since they are current.
516
517 Use the following steps to adapt the tutorial to MySQL.  Thanks to Jim
518 Howard for the help.
519
520 =over 4
521
522 =item *
523
524 Chapter 3: Catalyst Basics
525
526 =over 4
527
528 =item *
529
530 Install the required software:
531
532 =over 4
533
534 =item *
535
536 The MySQL database server and client utility.
537
538 =item *
539
540 The Perl C<DBD::MySQL> module
541
542 =back
543
544 For CentOS users (see
545 L<Catalyst::Manual::Installation::CentOS4|Catalyst::Manual::Installation::CentOS4>),
546 you can use the following commands to install the software and start the MySQL
547 daemon:
548
549     yum -y install mysql mysql-server
550     service mysqld start
551
552 =item *
553
554 Create the database and set the permissions:
555
556     $ mysql
557     Welcome to the MySQL monitor.  Commands end with ; or \g.
558     Your MySQL connection id is 2 to server version: 4.1.20
559     
560     Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
561     
562     mysql> create database myapp;
563     Query OK, 1 row affected (0.01 sec)
564     
565     mysql> grant all on myapp.* to tutorial@'localhost';
566     Query OK, 0 rows affected (0.00 sec)
567     
568     mysql> flush privileges;
569     Query OK, 0 rows affected (0.00 sec)
570     
571     mysql> quit
572     Bye
573
574 =item *
575
576 Create the C<.sql> file and load the data:
577
578 =over 4
579
580 =item *
581
582 Open the C<myapp01_mysql.sql> in your editor and enter:
583
584     --
585     -- Create a very simple database to hold book and author information
586     --
587     DROP TABLE IF EXISTS books;
588     DROP TABLE IF EXISTS book_authors;
589     DROP TABLE IF EXISTS authors;
590     CREATE TABLE books (
591            id          INT(11) PRIMARY KEY AUTO_INCREMENT,
592            title       TEXT ,
593            rating      INT(11)
594     );
595     -- 'book_authors' is a many-to-many join table between books & authors
596     CREATE TABLE book_authors (
597            book_id     INT(11),
598            author_id   INT(11),
599            PRIMARY KEY (book_id, author_id)
600     );
601     CREATE TABLE authors (
602            id          INT(11) PRIMARY KEY AUTO_INCREMENT,
603            first_name  TEXT,
604            last_name   TEXT
605     );
606     ---
607     --- Load some sample data
608     ---
609     INSERT INTO books VALUES (1, 'CCSP SNRS Exam Certification Guide', 5);
610     INSERT INTO books VALUES (2, 'TCP/IP Illustrated, Volume 1', 5);
611     INSERT INTO books VALUES (3, 'Internetworking with TCP/IP Vol.1', 4);
612     INSERT INTO books VALUES (4, 'Perl Cookbook', 5);
613     INSERT INTO books VALUES (5, 'Designing with Web Standards', 5);
614     INSERT INTO authors VALUES (1, 'Greg', 'Bastien');
615     INSERT INTO authors VALUES (2, 'Sara', 'Nasseh');
616     INSERT INTO authors VALUES (3, 'Christian', 'Degu');
617     INSERT INTO authors VALUES (4, 'Richard', 'Stevens');
618     INSERT INTO authors VALUES (5, 'Douglas', 'Comer');
619     INSERT INTO authors VALUES (6, 'Tom', 'Christiansen');
620     INSERT INTO authors VALUES (7, ' Nathan', 'Torkington');
621     INSERT INTO authors VALUES (8, 'Jeffrey', 'Zeldman');
622     INSERT INTO book_authors VALUES (1, 1);
623     INSERT INTO book_authors VALUES (1, 2);
624     INSERT INTO book_authors VALUES (1, 3);
625     INSERT INTO book_authors VALUES (2, 4);
626     INSERT INTO book_authors VALUES (3, 5);
627     INSERT INTO book_authors VALUES (4, 6);
628     INSERT INTO book_authors VALUES (4, 7);
629     INSERT INTO book_authors VALUES (5, 8);
630
631 =item *
632
633 Load the data:
634
635     mysql -ututorial myapp < myapp01_mysql.sql
636
637 =item *
638
639 Make sure the data loaded correctly:
640
641     $ mysql -ututorial myapp
642     Reading table information for completion of table and column names
643     You can turn off this feature to get a quicker startup with -A
644     
645     Welcome to the MySQL monitor.  Commands end with ; or \g.
646     Your MySQL connection id is 4 to server version: 4.1.20
647     
648     Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
649     
650     mysql> show tables;
651     +-----------------+
652     | Tables_in_myapp |
653     +-----------------+
654     | authors         |
655     | book_authors    |
656     | books           |
657     +-----------------+
658     3 rows in set (0.00 sec)
659     
660     mysql> select * from books;
661     +----+------------------------------------+--------+
662     | id | title                              | rating |
663     +----+------------------------------------+--------+
664     |  1 | CCSP SNRS Exam Certification Guide |      5 |
665     |  2 | TCP/IP Illustrated, Volume 1       |      5 |
666     |  3 | Internetworking with TCP/IP Vol.1  |      4 |
667     |  4 | Perl Cookbook                      |      5 |
668     |  5 | Designing with Web Standards       |      5 |
669     +----+------------------------------------+--------+
670     5 rows in set (0.00 sec)
671     
672     mysql>
673
674 =back
675
676 =item *
677
678 Update the model:
679
680 =over 4
681
682 =item *
683
684 Delete the existing model:
685
686     rm lib/MyApp/Model/MyAppDB.pm
687
688 =item *
689
690 Regenerate the model using the Catalyst "_create.pl" script:
691
692     script/myapp_create.pl model DB DBIC::Schema MyApp::Schema \
693         dbi:mysql:myapp '_username_here_' '_password_here_' '{ AutoCommit => 1 }'
694
695 =back
696
697 =back
698
699 =item *
700
701 Chapter 5: Authentication
702
703 =over 4
704
705 =item *
706
707 Create the C<.sql> file for the user/roles data:
708
709 Open C<myapp02_mysql.sql> in your editor and enter:
710
711     --
712     -- Add users and roles tables, along with a many-to-many join table
713     --
714     CREATE TABLE users (
715             id            INT(11) PRIMARY KEY,
716             username      TEXT,
717             password      TEXT,
718             email_address TEXT,
719             first_name    TEXT,
720             last_name     TEXT,
721             active        INT(11)
722     );
723     CREATE TABLE roles (
724             id   INTEGER PRIMARY KEY,
725             role TEXT
726     );
727     CREATE TABLE user_roles (
728             user_id INT(11),
729             role_id INT(11),
730             PRIMARY KEY (user_id, role_id)
731     );
732     --
733     -- Load up some initial test data
734     --
735     INSERT INTO users VALUES (1, 'test01', 'mypass', 't01@na.com', 'Joe',  'Blow', 1);
736     INSERT INTO users VALUES (2, 'test02', 'mypass', 't02@na.com', 'Jane', 'Doe',  1);
737     INSERT INTO users VALUES (3, 'test03', 'mypass', 't03@na.com', 'No',   'Go',   0);
738     INSERT INTO roles VALUES (1, 'user');
739     INSERT INTO roles VALUES (2, 'admin');
740     INSERT INTO user_roles VALUES (1, 1);
741     INSERT INTO user_roles VALUES (1, 2);
742     INSERT INTO user_roles VALUES (2, 1);
743     INSERT INTO user_roles VALUES (3, 1);
744
745 =item *
746
747 Load the user/roles data:
748
749     mysql -ututorial myapp < myapp02_mysql.sql
750
751 =item *
752
753 Create the C<.sql> file for the hashed password data:
754
755 Open C<myapp03_mysql.sql> in your editor and enter:
756
757     --
758     -- Convert passwords to SHA-1 hashes
759     --
760     UPDATE users SET password = 'e727d1464ae12436e899a726da5b2f11d8381b26' WHERE id = 1;
761     UPDATE users SET password = 'e727d1464ae12436e899a726da5b2f11d8381b26' WHERE id = 2;
762     UPDATE users SET password = 'e727d1464ae12436e899a726da5b2f11d8381b26' WHERE id = 3;
763
764 =item *
765
766 Load the user/roles data:
767
768     mysql -ututorial myapp < myapp03_mysql.sql
769
770 =back
771
772 =back
773
774
775 =head1 AUTHOR
776
777 Kennedy Clark, C<hkclark@gmail.com>
778
779 Please report any errors, issues or suggestions to the author.  The
780 most recent version of the Catalyst Tutorial can be found at
781 L<http://dev.catalyst.perl.org/repos/Catalyst/Catalyst-Manual/5.70/trunk/lib/Catalyst/Manual/Tutorial/>.
782
783 Copyright 2006-2008, Kennedy Clark, under Creative Commons License
784 (L<http://creativecommons.org/licenses/by-sa/3.0/us/>).