3 Catalyst::Manual::Tutorial::Appendices - Catalyst Tutorial - Chapter 10: Appendices
8 This is B<Chapter 10 of 10> for the Catalyst tutorial.
10 L<Tutorial Overview|Catalyst::Manual::Tutorial>
16 L<Introduction|Catalyst::Manual::Tutorial::Intro>
20 L<Catalyst Basics|Catalyst::Manual::Tutorial::CatalystBasics>
24 L<More Catalyst Basics|Catalyst::Manual::Tutorial::MoreCatalystBasics>
28 L<Basic CRUD|Catalyst::Manual::Tutorial::BasicCRUD>
32 L<Authentication|Catalyst::Manual::Tutorial::Authentication>
36 L<Authorization|Catalyst::Manual::Tutorial::Authorization>
40 L<Debugging|Catalyst::Manual::Tutorial::Debugging>
44 L<Testing|Catalyst::Manual::Tutorial::Testing>
48 L<Advanced CRUD|Catalyst::Manual::Tutorial::AdvancedCRUD>
59 This chapter of the tutorial provides supporting information relevant to
60 the Catalyst tutorial.
63 =head1 APPENDIX 1: CUT AND PASTE FOR POD-BASED EXAMPLES
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
69 =head2 "Un-indenting" with Vi/Vim
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>:
82 Removes four leading spaces from the entire file (from the first line,
83 C<0>, to the last line, C<$>).
89 A shortcut for the previous item (C<%> specifies the entire file; so
90 this removes four leading spaces from every line).
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.
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).
108 =head2 "Un-indenting" with Emacs
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:
114 M-x replace-regexp<RET>
115 Replace regexp: ^ <RET>
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.
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
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:
136 L<http://www.gnu.org/software/emacs/manual/html_node/emacs/Indentation-Comman>
139 =head1 APPENDIX 2: USING POSTGRESQL AND MYSQL
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.
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.
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
168 Chapter 3: More Catalyst Basics
174 Install the PostgreSQL server and client and DBD::Pg:
176 If you are following along in Debian 5, you can quickly install these
177 items via this command:
179 sudo aptitude install postgresql libdbd-pg-perl libdatetime-format-pg-perl
181 To configure the permissions, you can open
182 C</etc/postgresql/8.3/main/pg_hba.conf> and change this line (near the
185 # "local" is for Unix domain socket connections only
186 local all all ident sameuser
190 # "local" is for Unix domain socket connections only
193 And then restart PostgreSQL:
195 sudo /etc/init.d/postgresql-8.3 restart
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
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
211 $ sudo -u postgres createdb -O catappuser catappdb
216 Create the C<.sql> file and load the data:
222 Open the C<myapp01_psql.sql> in your editor and enter:
225 -- Drops just in case you are reloading
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;
235 -- Create a very simple database to hold book and author information
238 id SERIAL PRIMARY KEY,
241 -- Manually add these later
242 -- created TIMESTAMP NOT NULL DEFAULT now(),
246 CREATE TABLE authors (
247 id SERIAL PRIMARY KEY,
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)
260 --- Load some sample data
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);
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"
293 psql:myapp01_psql.sql:15: NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "book_authors_pkey" for table "book_authors"
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"
305 Make sure the data loaded correctly:
307 $ psql -U catappuser -W catappdb
308 Password for user catappuser: <catalyst>
309 Welcome to psql 8.3.7, the PostgreSQL interactive terminal.
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
319 Schema | Name | Type | Owner
320 --------+--------------+-------+------------
321 public | authors | table | catappuser
322 public | book_authors | table | catappuser
323 public | books | table | catappuser
326 catappdb=> select * from books;
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
342 After the steps where you:
346 create lib/MyAppDB.pm
348 create lib/MyAppDB/Book.pm
350 create lib/MyAppDB/Author.pm
352 create lib/MyAppDB/BookAuthor.pm
357 Generate the model using the Catalyst "_create.pl" script:
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 }'
368 Chapter 4: Basic CRUD
370 Add Datetime Columns to Our Existing Books Table
372 $ psql -U catappuser -W catappdb
374 catappdb=> ALTER TABLE books ADD created TIMESTAMP NOT NULL DEFAULT now();
376 catappdb=> ALTER TABLE books ADD updated TIMESTAMP;
380 Re-generate the model using the Catalyst "_create.pl" script:
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 }'
389 Chapter 5: Authentication
395 Create the C<.sql> file for the user/roles data:
397 Open C<myapp02_psql.sql> in your editor and enter:
400 -- Add users and roles tables, along with a many-to-many join table
404 id SERIAL PRIMARY KEY,
414 id SERIAL PRIMARY KEY,
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)
425 -- Load up some initial test data
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);
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"
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"
452 psql:myapp02_psql.sql:24: NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "user_roles_pkey" for table "user_roles"
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
478 Modify C<set_hashed_passwords.pl> to match the following (the only difference
479 is the C<connect> line):
488 my $schema = MyApp::Schema->connect('dbi:Pg:dbname=catappdb', 'catappuser', 'catalyst');
490 my @users = $schema->resultset('Users')->all;
492 foreach my $user (@users) {
493 $user->password('mypass');
497 Run the C<set_hashed_passwords.pl> as per the "normal" flow of the
500 $ perl -Ilib set_hashed_passwords.pl
502 You can verify that it worked with this command:
504 $ psql -U catappuser -W catappdb -c "select * from users"
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.
517 Use the following steps to adapt the tutorial to MySQL. Thanks to Jim
524 Chapter 3: Catalyst Basics
530 Install the required software:
536 The MySQL database server and client utility.
540 The Perl C<DBD::MySQL> module
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
549 yum -y install mysql mysql-server
554 Create the database and set the permissions:
557 Welcome to the MySQL monitor. Commands end with ; or \g.
558 Your MySQL connection id is 2 to server version: 4.1.20
560 Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
562 mysql> create database myapp;
563 Query OK, 1 row affected (0.01 sec)
565 mysql> grant all on myapp.* to tutorial@'localhost';
566 Query OK, 0 rows affected (0.00 sec)
568 mysql> flush privileges;
569 Query OK, 0 rows affected (0.00 sec)
576 Create the C<.sql> file and load the data:
582 Open the C<myapp01_mysql.sql> in your editor and enter:
585 -- Create a very simple database to hold book and author information
587 DROP TABLE IF EXISTS books;
588 DROP TABLE IF EXISTS book_authors;
589 DROP TABLE IF EXISTS authors;
591 id INT(11) PRIMARY KEY AUTO_INCREMENT,
595 -- 'book_authors' is a many-to-many join table between books & authors
596 CREATE TABLE book_authors (
599 PRIMARY KEY (book_id, author_id)
601 CREATE TABLE authors (
602 id INT(11) PRIMARY KEY AUTO_INCREMENT,
607 --- Load some sample data
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);
635 mysql -ututorial myapp < myapp01_mysql.sql
639 Make sure the data loaded correctly:
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
645 Welcome to the MySQL monitor. Commands end with ; or \g.
646 Your MySQL connection id is 4 to server version: 4.1.20
648 Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
658 3 rows in set (0.00 sec)
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)
684 Delete the existing model:
686 rm lib/MyApp/Model/MyAppDB.pm
690 Regenerate the model using the Catalyst "_create.pl" script:
692 script/myapp_create.pl model DB DBIC::Schema MyApp::Schema \
693 dbi:mysql:myapp '_username_here_' '_password_here_' '{ AutoCommit => 1 }'
701 Chapter 5: Authentication
707 Create the C<.sql> file for the user/roles data:
709 Open C<myapp02_mysql.sql> in your editor and enter:
712 -- Add users and roles tables, along with a many-to-many join table
715 id INT(11) PRIMARY KEY,
724 id INTEGER PRIMARY KEY,
727 CREATE TABLE user_roles (
730 PRIMARY KEY (user_id, role_id)
733 -- Load up some initial test data
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);
747 Load the user/roles data:
749 mysql -ututorial myapp < myapp02_mysql.sql
753 Create the C<.sql> file for the hashed password data:
755 Open C<myapp03_mysql.sql> in your editor and enter:
758 -- Convert passwords to SHA-1 hashes
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;
766 Load the user/roles data:
768 mysql -ututorial myapp < myapp03_mysql.sql
777 Kennedy Clark, C<hkclark@gmail.com>
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/>.
783 Copyright 2006-2008, Kennedy Clark, under Creative Commons License
784 (L<http://creativecommons.org/licenses/by-sa/3.0/us/>).