2012年6月3日日曜日

Masakazu's Weblog


Catalyst::Manual::Tutorial::CatalystBasics – Catalyst Tutorial – Part 2: Catalyst Application Development Basics の対訳。2008/01/18 時点での最新版 Catalyst-Manual-5.701003.tar.gz を元にしています。

書きかけなんだけど興味がなくなり更新見込みがなくなったので公開。

誤訳がありましたらコメントにてご指摘ください。

Catalyst::Manual::Tutorial::CatalystBasics – Catalyst Tutorial – Part 2: Catalyst Application Development Basics

Catalyst::Manual::Tutorial::CatalystBasics – Catalyst チュートリアル – 第二部: Catalyst アプリケーション開発の基礎

This is Part 2 of 9 for the Catalyst tutorial.

9 つある Catalyst チュートリアルのうちの 2 つめです。

Tutorial Overview

チュートリアルの概要

  1. Introduction
    導入
  2. Catalyst Basics
    Catalyst の基礎
  3. Basic CRUD
    基礎的な CRUD
  4. Authentication
    認証
  5. Authorization
    承認
  6. Debugging
    デバッグ
  7. Testing
    テスト
  8. Advanced CRUD
    高度な CRUD
  9. Appendices
    補遺

In this part of the tutorial, we will create a very basic Catalyst web application. Though simple in many respects, this section will already demonstrate a number of powerful capabilities such as:

このパートでは、とても基本的な Catalyst Web アプリケーションを作ります。シンプルな多くの側面を通して、次のようないくつかのパワフルな能力をデモします:

  • Helper Scriptsヘルパスクリプト

    Catalyst helper scripts that can be used to rapidly bootstrap the skeletal structure of an application.

    Catalyst ヘルパスクリプトはアプリケーションのひな形構造を素早く立ち上げるために利用されます。

  • MVCMVC

    Model/View/Controller (MVC) provides an architecture that facilitates a clean "separation of control" between the different portions of your application. Given that many other documents cover this subject in detail, MVC will not be discussed in depth here (for an excellent introduction to MVC and general Catalyst concepts, please see Catalyst::Manual::About. In short:

    モデル/ビュー/コントローラ(MVC) はアプリケーションの異なる部品間で容易にクリーンな "制御の分離" を行えるようにするためのアーキテクチャです。この件つついては詳細に説明する文書が多くあるので、ここではこれ以上深く掘り下げません(MVC と一般的な Catalyst のコンセプトについてのすばらしい導入については Catalyst::Manual::Abount を参照してください)。簡単に説明すると:

    • Modelモデル

      The model usually represents a data store. In most applications, the model equates to the objects that are created from and saved to your SQL database.

      モデルはたいていデータストアを表現します。多くのアプリケーションでは、モデルは SQL データベースに作られ、保存されるオブジェクトと同じです。

    • Viewビュー

      The view takes model objects and renders them into something for the end user to look at. Normally this involves a template-generation tool that creates HTML for the user's web browser, but it could easily be code that generates other forms such as PDF documents, e-mails, or Excel spreadsheets.

      ビューはモデルオブジェクトを得てそれらをエンドユーザに見えるよう描画します。通常ユーザの Web ブラウザのための HTML を生成するテンプレート生成ツールを含みますが、それ以外のフォーム例えば PDF ドキュメントや e-mail や Excel シートなどの場合もあります。

    • Controller

      As suggested by its name, the controller takes user requests and routes them to the necessary model and view.

      名前の通り、コントローラはユーザのリクエストを得て必要なモデルとビユーへ送ります。

  • ORMORM

    The use of Object-Relational Mapping (ORM) technology for database access. Specifically, ORM provides an automated and standardized means to persist and restore objects to/from a relational database.

    データベースへのアクセスにオブジェクト-リレーショナルマッピング(ORM)技術を用います。特に、 ORM はオブジェクトをリレーショナルデータベースへ書き込んだり読み出したりするための自動的で標準かされた方法を提供します。

You can checkout the source code for this example from the catalyst subversion repository as per the instructions in Catalyst::Manual::Tutorial::Intro.

この例のソースコードを Catalyst Subversion リポジトリから Catalyst::Manual::Tutorial::Intro にある手順でチェックアウトできます。

CREATE A CATALYST PROJECT

Catalyst プロジェクトを作る

Catalyst provides a number of helper scripts that can be used to quickly flesh out the basic structure of your application. All Catalyst projects begin with the catalyst.pl helper (see Catalyst::Helper for more information on helpers). Also note that as of Catalyst 5.7000, you will not have the helper scripts unless you install both Catalyst::Runtime and Catalyst::Devel.

Catalyst にはアプリケーションの基本的な構造を素早く具体化するためのヘルパスクリプトがいくつか提供されています。すべての Catalyst プロジェクトは catalyst.pl ヘルパからはじまります(ヘルパに関する詳細な情報は Catalyst::Helper を参照してください)。Catalyst 5.7000 では Catalyst::Runtime と Catalyst::Devel の両方がインストールされていないとヘルパスクリプトを利用できないので注意してください。

In the case of this tutorial, use the Catalyst catalyst.pl script to initialize the framework for an application called MyApp:

このチュートリアルでは、 MyAppと呼ばれるアプリケーションのフレームワークを初期化するため catalyst.pl というスクリプトを用います:

$ catalyst.pl MyApp  created "MyApp"  created "MyApp/script"  created "MyApp/lib"  created "MyApp/root"  ...  created "MyApp/script/myapp_create.pl"  $ cd MyApp

The catalyst.pl helper script will display the names of the directories and files it creates.

catalyst.pl ヘルパスクリプトは作成したディレクトリとファイルを表示します。

Though it's too early for any significant celebration, we already have a functioning application. Run the following command to run this application with the built-in development web server:

お祝いするにはまだ早いですが、すでに機能するアプリケーションになりました。以下のコマンドを実行することで組み込みの開発 Web サーバでアクリケーションを実行できます:

$ script/myapp_server.pl  [debug] Debug messages enabled  [debug] Loaded plugins:  .----------------------------------------------------------------------------.  | Catalyst::Plugin::ConfigLoader  0.13                                       |  | Catalyst::Plugin::Static::Simple  0.14                                     |  '----------------------------------------------------------------------------'  [debug] Loaded dispatcher "Catalyst::Dispatcher"  [debug] Loaded engine "Catalyst::Engine::HTTP"  [debug] Found home "/home/me/MyApp"  [debug] Loaded Config "/home/me/myapp.yml"  [debug] Loaded components:  .-----------------------------------------------------------------+----------.  | Class                                                           | Type     |  +-----------------------------------------------------------------+----------+  | MyApp::Controller::Root                                         | instance |  '-----------------------------------------------------------------+----------'  [debug] Loaded Private actions:  .----------------------+--------------------------------------+--------------.  | Private              | Class                                | Method       |  +----------------------+--------------------------------------+--------------+  | /default             | MyApp::Controller::Root              | default      |  | /end                 | MyApp::Controller::Root              | end          |  '----------------------+--------------------------------------+--------------'  [info] MyApp powered by Catalyst 5.7002  You can connect to your server at http://localhost:3000

NOTE: Be sure you run the script/myapp_server.pl command from the 'base' directory of your application, not inside the script directory itself. It doesn't make a difference at this point, but it will as soon as we get the database going in the next section.

ノート: script ディレクトリの中からではなく、アプリケーションの 'ベース' ディレクトリから script/myapp_server.pl コマンドを実行することに注意してください。現時点ではいずれにせよかわりありませんが、時節でデータベースが出た時点でかわってきます。

Point your web browser to http://localhost:3000 (substituting a different hostname or IP address as appropriate) and you should be greeted by the Catalyst welcome screen. Information similar to the following should be appended to the logging output of the development server:

Web ブラウザで http://localhost:3000 を参照すると(異なるホスト名や IP アドレスなど適するものに置き換えてください)、 Catalyst のようこそ画面が表示されるはずです。開発サーバでは以下のようなロギング出力が表示されるはずです:

[info] *** Request 1 (0.043/s) [6003] [Fri Jul  7 13:32:53 2006] ***  [debug] "GET" request for "/" from "127.0.0.1"  [info] Request took 0.067675s (14.777/s)  .----------------------------------------------------------------+-----------.  | Action                                                         | Time      |  +----------------------------------------------------------------+-----------+  | /default                                                       | 0.002844s |  | /end                                                           | 0.000207s |  '----------------------------------------------------------------+-----------'

Press Ctrl-C to break out of the development server.

Ctrl-C で開発サーバを停止します。

CREATE A SQLITE DATABASE

SQLite データベースの作成

In this step, we make a text file with the required SQL commands to create a database table and load some sample data. Open myapp01.sql in your editor and enter:


大学院のプログラムが取るべき臨床心理士

このステップでは、データベーステーブルを作りいくつかサンプルデータを読み込むために必要となる SQL コマンドを書いたテキストファイルを作ります。エディタで myapp01.sql を開き以下の内容を書いてください:

--  -- Create a very simple database to hold book and author information  --  CREATE TABLE books (  id          INTEGER PRIMARY KEY,  title       TEXT ,  rating      INTEGER  );  -- 'book_authors' is a many-to-many join table between books & authors  CREATE TABLE book_authors (  book_id     INTEGER,  author_id   INTEGER,  PRIMARY KEY (book_id, author_id)  );  CREATE TABLE authors (  id          INTEGER PRIMARY KEY,  first_name  TEXT,  last_name   TEXT  );  ---  --- Load some sample data  ---  INSERT INTO books VALUES (1, 'CCSP SNRS Exam Certification Guide', 5);  INSERT INTO books VALUES (2, 'TCP/IP Illustrated, Volume 1', 5);  INSERT INTO books VALUES (3, 'Internetworking with TCP/IP Vol.1', 4);  INSERT INTO books VALUES (4, 'Perl Cookbook', 5);  INSERT INTO books VALUES (5, 'Designing with Web Standards', 5);  INSERT INTO authors VALUES (1, 'Greg', 'Bastien');  INSERT INTO authors VALUES (2, 'Sara', 'Nasseh');  INSERT INTO authors VALUES (3, 'Christian', 'Degu');  INSERT INTO authors VALUES (4, 'Richard', 'Stevens');  INSERT INTO authors VALUES (5, 'Douglas', 'Comer');  INSERT INTO authors VALUES (6, 'Tom', 'Christiansen');  INSERT INTO authors VALUES (7, 'Nathan', 'Torkington');  INSERT INTO authors VALUES (8, 'Jeffrey', 'Zeldman');  INSERT INTO book_authors VALUES (1, 1);  INSERT INTO book_authors VALUES (1, 2);  INSERT INTO book_authors VALUES (1, 3);  INSERT INTO book_authors VALUES (2, 4);  INSERT INTO book_authors VALUES (3, 5);  INSERT INTO book_authors VALUES (4, 6);  INSERT INTO book_authors VALUES (4, 7);  INSERT INTO book_authors VALUES (5, 8);

TIP: See Appendix 1 for tips on removing the leading spaces when cutting and pasting example code from POD-based documents.

TIP: POD ベースのドキュメントからサンプルコードをコピー&ペーストし最初にあるスペースを取り除く方法は補遺 1 をみてください。

Then use the following command to build a myapp.db SQLite database:

次のコマンドを実行し myapp.db SQLite データベースを構築します:

$ sqlite3 myapp.db < myapp01.sql

If you need to create the database more than once, you probably want to issue the rm myapp.db command to delete the database before you use the sqlite3 myapp.db < myapp01.sql command.

もし一回以上データベースを作成したいときは sqlite3 myapp.db < myapp01.sql を実行する前に rm myapp.db でデータベースを消したいと思うでしょう。

Once the myapp.db database file has been created and initialized, you can use the SQLite command line environment to do a quick dump of the database contents:

一度 myapp.db データベースが作成され、初期化されれば、 SQLite コマンドライン環境でデータベースの内容のクイックダンプを取得できます:

$ sqlite3 myapp.db  SQLite version 3.2.2  Enter ".help" for instructions  sqlite> select * from books;  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  sqlite> .q  $

Or:

或は:

$ sqlite3 myapp.db "select * from books"  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

As with most other SQL tools, if you are using the full "interactive" environment you need to terminate your SQL commands with a ";" (it's not required if you do a single SQL statement on the command line). Use ".q" to exit from SQLite from the SQLite interactive mode and return to your OS command prompt.

ほとんどの他の SQL ツールのように、もし完全に "インタラクティブ" な環境を使っているのであれば SQL コマンドを ";" で終端する必要がある(これはコマンドラインからひとつの SQL 分を実行するときは必要ない)。SQLite のインタラクティブモードから抜けたいときは ".q" を使う。そうすると OS のコマンドプロンプトに戻ることができる。

EDIT THE LIST OF CATALYST PLUGINS

Catalyst プラグインリストの編集

One of the greatest benefits of Catalyst is that it has such a large library of plugins available. Plugins are used to seamlessly integrate existing Perl modules into the overall Catalyst framework. In general, they do this by adding additional methods to the context object (generally written as $c) that Catalyst passes to every component throughout the framework.

Catalyst を使う最も大きな利点のひとつは利用可能なプラグインライブラリ大量に存在することです。プラグインは Catalyst フレームワークを超えてすでに存在する Perl モジュールとシームレスに利用できます。一般に、フレームワークないのすべてのコンポーネントに渡される context オブジェクト(一般に $c と書かれます)に追加のメソッドを加えることによって実現します。

By default, Catalyst enables three plugins/flags:

デフォルトでは、 Catalyst は以下の 3 つのプラグインとフラグを有効にします:

  • -Debug Flag-Debug フラグ

    Enables the Catalyst debug output you saw when we started the script/myapp_server.pl development server earlier. You can remove this plugin when you place your application into production.

    先ほど開発サーバーで script/myapp_server.pl を実行した際にみた Catalyst デバッグ出力を有効にします。アプリケーションを製品として設置する際にこのプラグインを削ることができます。

    As you may have noticed, -Debug is not a plugin, but a flag. Although most of the items specified on the use Catalyst line of your application class will be plugins, Catalyst supports a limited number of flag options (of these, -Debug is the most common). See the documentation for Catalyst.pm to get details on other flags (currently -Engine, -Home, and -Log).

    気づいたかもしれませんが -Debug はプラグインではなく、フラグです。しかしながら、ほとんどの use Catalyst 行で指定されるアイテムはプラグインです。 Catalyst でサポートしているフラグの数は限られています(これらのなかで -Debug が最も一般的です)。他のフラグ(現時点では -Engine、 -Home、そして -Log があります)の詳細については Catalyst.pm のドキュメントを参照してください。

    If you prefer, you can use the $c->debug method to enable debug messages.

    お好みに応じて、 $c->debug というメソッドを用いてデバッグメッセージを有効化することもできます。

  • Catalyst::Plugin::ConfigLoaderCatalyst::Plugin::ConfigLoader

    ConfigLoader provides an automatic way to load configurable parameters for your application from a central YAML file (versus having the values hard-coded inside your Perl modules). If you have not been exposed to YAML before, it is a human-readable data serialization format that can be used to read (and write) values to/from text files. We will see how to use this feature of Catalyst during the authentication and authorization sections (Part 4 and Part 5).

    ConfigLoader はあなたのアプリケーションで(Perl コード中に値をハードコードする代わりに)自動的に中央に配置した YAML ファイルから設定パラメータを取得する方法を提供します。YAML に触れたことがない方のために説明すると、 YAML はテキストファイル(から/へ)データを読む(もしくは書く)ことができる人が読めるデータ永続化フォーマットです。認証と承認の箇所(第四部と第五部)でこれらの機能の使い方をみます。

  • Catalyst::Plugin::Static::SimpleCatalyst::Plugin::Static::Simple

    Static::Simple provides an easy method of serving static content such as images and CSS files under the development server.

    Static::Simple は開発サーバで画像や CSS ファイルといったスタティックなコンテンツを簡単に提供するための方法を提供します。

To modify the list of plugins, edit lib/MyApp.pm (this file is generally referred to as your application class) and delete the line with:

プラグインリストを変更するためには、 lib/MyApp.pm(このファイルはアプリケーションクラスとして参照されます)を編集し、以下の行を:

use Catalyst qw/-Debug ConfigLoader Static::Simple/;

Replace it with:

以下のように差し替えます:

use Catalyst qw/  -Debug  ConfigLoader  Static::Simple  StackTrace  /;

This tells Catalyst to start using one new plugin:

上記では Catalyst に対して新しいプラグインを使い始めることを教えています。

  • Catalyst::Plugin::StackTraceCatalyst::Plugin::StackTrace

    Adds a stack trace to the standard Catalyst "debug screen" (this is the screen Catalyst sends to your browser when an error occurs).

    標準の Catalyst "デバッグ画面"(エラーが起こったときに Catalyst がブラウザに対して表示する画面です)にスタックトレースを追加します。

    Note: StackTrace output appears in your browser, not in the console window from which you're running your application, which is where logging output usually goes.

    StackTrace 出力はアプリケーションを実行しているコンソール上ではなくブラウザ上に現れます。ログ出力は通常こちらに現れます。

Note that when specifying plugins on the use Catalyst line, you can omit Catalyst::Plugin:: from the name. Additionally, you can spread the plugin names across multiple lines as shown here, or place them all on one (or more) lines as with the default configuration.

use Catalyst 行でプラグインを指定する際、その名前から Catalyst::Plugin:: を省くことができます。また、ここに書いたようにプラグイン名を複数業にわたって書くことも、デフォルトの設定のようにすべてを一行(あるいはもっと)に書くこともできます。

TIP: You may see examples that include the Catalyst::Plugin::DefaultEnd plugins. As of Catalyst 5.7000, DefaultEnd has been deprecated in favor of Catalyst::Action::RenderView (as the name of the package suggests, RenderView is not a plugin, but an action). The purpose of both is essentially the same: forward processing to the view to be rendered. Applications generated under 5.7000 should automatically use RenderView and "just work" for most applications. For more information on RenderView and the various options for forwarding to your view logic, please refer to the "Using RenderView for the Default View" section under "CATALYST VIEWS" below.


自動販売機対子供の肥満

Catalyst::Plugin::DefaultEnd を利用しているサンプルを見かけるかもしれません。Catalyst 5.7000 現在、 DefaultEnd は Catalyst::Action::RenderView(名前の通り RenderView はプラグインではなくアクションです)により非推奨となっています。これらの目的は本質的には一緒です: 表示されるべきビューへ処理を進めます。 5.7000 の元に生成されたアプリケーションは自動的に RenderView を利用し、ほとんどのアプリケーションで"うまく動きます"。 RenderView の詳細な情報とビューロジックを転送する多彩なオプションについては以下の "Catalyst ビュー" の "デフォルトのビューに RenderView を使う" を参照してください。

DATABASE ACCESS WITH DBIx::Class

DBIx::Class によるデータベースアクセス

Catalyst can be used with virtually any form of persistent datastore available via Perl. For example, Catalyst::Model::DBI can be used to easily access databases through the traditional Perl DBI interface. However, most Catalyst applications use some form of ORM technology to automatically create and save model objects as they are used. Although Tony Bowden's Class::DBI has been the traditional Perl ORM engine, Matt Trout's DBIx::Class (abbreviated as "DBIC") has rapidly emerged as the Perl-based ORM technology of choice. Most new Catalyst applications rely on DBIC, as will this tutorial.

Catalyst は Perl で利用可能なすべての永続データストアを仮想的に利用できます。例えば Catalyst::Model::DBI を伝統的な Perl の DBI インターフェースを通じた簡単なデータベースアクセスに利用できます。しかし、ほとんどの Catalyst アプリケーションは利用するモデルオブジェクトを自動的に生成したり保存したりするためになにかしらの ORM 技術を利用します。Tony Bowden の Class:DBI は伝統的な Perl ORM エンジンですが、 Matt Trout の DBIx::Class("DBIC" と略されます) は Perl での ORM 技術の選択として急に浮かび上がってきました。ほとんどの新しい Catalyst アプリケーションは DBIC に依っていますので、このチュートリアルでも従います。

Note: See Catalyst::Model::CDBI for more information on using Catalyst with Class::DBI.

ノート: Class::DBI で Catalyst を利用するときの詳細な情報は Catalyst::Model::CDBI を参照してください。

Create a DBIC Schema File

DBIC スキーマファイルの作成

DBIx::Class uses a schema file to load other classes that represent the tables in your database (DBIC refers to these "table objects" as "result sources"; see DBIx::Class::ResultSource). In this case, we want to load the model object for the books, book_authors, and authors tables created in the previous step.

Create lib/MyAppDB.pm in your editor and insert:

package MyAppDB;  =head1 NAME  MyAppDB - DBIC Schema Class  =cut  # Our schema needs to inherit from 'DBIx::Class::Schema'  use base qw/DBIx::Class::Schema/;  # Need to load the DB Model classes here.  # You can use this syntax if you want:  #    __PACKAGE__->load_classes(qw/Book BookAuthor Author/);  # Also, if you simply want to load all of the classes in a directory  # of the same name as your schema class (as we do here) you can use:  #    __PACKAGE__->load_classes(qw//);  # But the variation below is more flexible in that it can be used to  # load from multiple namespaces.  __PACKAGE__->load_classes({  MyAppDB => [qw/Book BookAuthor Author/]  });  1;

Note: __PACKAGE__ is just a shorthand way of referencing the name of the package where it is used. Therefore, in MyAppDB.pm, __PACKAGE__ is equivalent to MyAppDB.

Note: As with any Perl package, we need to end the last line with a statement that evaluates to true. This is customarily done with 1 on a line by itself as shown above.

Create the DBIC "Result Source" Files

In this step, we create "table classes" (again, these are called a "result source" classes in DBIC) that act as model objects for the books, book_authors, and authors tables in our database.

First, create a directory to hold the class:

$ mkdir lib/MyAppDB

Then create lib/MyAppDB/Book.pm in your editor and enter:

package MyAppDB::Book;  use base qw/DBIx::Class/;  # Load required DBIC stuff  __PACKAGE__->load_components(qw/PK::Auto Core/);  # Set the table name  __PACKAGE__->table('books');  # Set columns in table  __PACKAGE__->add_columns(qw/id title rating/);  # Set the primary key for the table  __PACKAGE__->set_primary_key(qw/id/);  #  # Set relationships:  #  # has_many():  #   args:  #     1) Name of relationship, DBIC will create accessor with this name  #     2) Name of the model class referenced by this relationship  #     3) Column name in *foreign* table  __PACKAGE__->has_many(book_authors => 'MyAppDB::BookAuthor', 'book_id');  # many_to_many():  #   args:  #     1) Name of relationship, 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().  __PACKAGE__->many_to_many(authors => 'book_authors', 'author');  =head1 NAME  MyAppDB::Book - A model object representing a book.  =head1 DESCRIPTION  This is an object that represents a row in the 'books' table of your application  database.  It uses DBIx::Class (aka, DBIC) to do ORM.  For Catalyst, this is designed to be used through MyApp::Model::MyAppDB.  Offline utilities may wish to use this class directly.  =cut  1;

This defines both a has_many and a many_to_many relationship. The many_to_many relationship is optional, but it makes it easier to map a book to its collection of authors. Without it, we would have to "walk" though the book_authors table as in $book->book_authors->first->author->last_name (we will see examples on how to use DBIC objects in your code soon, but note that because $book->book_authors can return multiple authors, we have to use first to display a single author). many_to_many allows us to use the shorter $book->authors->first->last_name. Note that you cannot define a many_to_many relationship without also having the has_many relationship in place.

Next, create lib/MyAppDB/Author.pm in your editor and enter:

package MyAppDB::Author;  use base qw/DBIx::Class/;  # Load required DBIC stuff  __PACKAGE__->load_components(qw/PK::Auto Core/);  # Set the table name  __PACKAGE__->table('authors');  # Set columns in table  __PACKAGE__->add_columns(qw/id first_name last_name/);  # Set the primary key for the table  __PACKAGE__->set_primary_key(qw/id/);  #  # Set relationships:  #  # has_many():  #   args:  #     1) Name of relationship, DBIC will create accessor with this name  #     2) Name of the model class referenced by this relationship  #     3) Column name in *foreign* table  __PACKAGE__->has_many(book_author => 'MyAppDB::BookAuthor', 'author_id');  # many_to_many():  #   args:  #     1) Name of relationship, 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().  __PACKAGE__->many_to_many(books => 'book_author', 'book');  =head1 NAME  MyAppDB::Author - A model object representing an author of a book (if a book has  multiple authors, each will be represented be separate Author object).  =head1 DESCRIPTION  This is an object that represents a row in the 'authors' table of your application  database.  It uses DBIx::Class (aka, DBIC) to do ORM.  For Catalyst, this is designed to be used through MyApp::Model::MyAppDB.  Offline utilities may wish to use this class directly.  =cut  1;

Finally, create lib/MyAppDB/BookAuthor.pm in your editor and enter:

package MyAppDB::BookAuthor;  use base qw/DBIx::Class/;  # Load required DBIC stuff  __PACKAGE__->load_components(qw/PK::Auto Core/);  # Set the table name  __PACKAGE__->table('book_authors');  # Set columns in table  __PACKAGE__->add_columns(qw/book_id author_id/);  # Set the primary key for the table  __PACKAGE__->set_primary_key(qw/book_id author_id/);  #  # Set relationships:  #  # belongs_to():  #   args:  #     1) Name of relationship, DBIC will create accessor with this name  #     2) Name of the model class referenced by this relationship  #     3) Column name in *this* table  __PACKAGE__->belongs_to(book => 'MyAppDB::Book', 'book_id');  # belongs_to():  #   args:  #     1) Name of relationship, DBIC will create accessor with this name  #     2) Name of the model class referenced by this relationship  #     3) Column name in *this* table  __PACKAGE__->belongs_to(author => 'MyAppDB::Author', 'author_id');  =head1 NAME  MyAppDB::BookAuthor - A model object representing the JOIN between an author and  a book.  =head1 DESCRIPTION  This is an object that represents a row in the 'book_authors' table of your  application database.  It uses DBIx::Class (aka, DBIC) to do ORM.  You probably won't need to use this class directly -- it will be automatically  used by DBIC where joins are needed.  For Catalyst, this is designed to be used through MyApp::Model::MyAppDB.  Offline utilities may wish to use this class directly.  =cut  1;

Note: This sample application uses a plural form for the database tables (e.g., books and authors) and a singular form for the model objects (e.g., Book and Author); however, Catalyst places no restrictions on the naming conventions you wish to use.

Use Catalyst::Model::DBIC::Schema To Load The Model Class

When Catalyst::Model::DBIC::Schema is in use, Catalyst essentially reads an existing copy of your database model and creates a new set of objects under MyApp::Model for use inside of Catalyst.

Note: With Catalyst::Model::DBIC::Schema you essentially end up with two sets of model classes (only one of which you write… the other set is created automatically in memory when your Catalyst application initializes). For this tutorial application, the important points to remember are: you write the result source files in MyAppDB, but within Catalyst you use the automatically created model classes in MyApp::Model.

Use the Catalyst::Helper::Model::DBIC::Schema helper script to create the model class that loads up the model we created in the previous step:

$ script/myapp_create.pl model MyAppDB DBIC::Schema MyAppDB dbi:SQLite:myapp.db '' '' '{ AutoCommit => 1 }'  exists "/root/dev/MyApp/script/../lib/MyApp/Model"  exists "/root/dev/MyApp/script/../t"  created "/root/dev/MyApp/script/../lib/MyApp/Model/MyAppDB.pm"  created "/root/dev/MyApp/script/../t/model_MyAppDB.t"

Where the first MyAppDB is the name of the class to be created by the helper in lib/MyApp/Model and the second MyAppDB is the name of existing schema file we created (in lib/MyAppDB.pm). You can see that the helper creates a model file under lib/MyApp/Model (Catalyst has a separate directory under lib/MyApp for each of the three parts of MVC: Model, View, and Controller [although older Catalyst applications often use the directories M, V, and C]).

CREATE A CATALYST CONTROLLER

Controllers are where you write methods that interact with user input–typically, controller methods respond to GET and POST messages from the user's web browser.

Use the Catalyst create script to add a controller for book-related actions:


すべての第八年生が知っておくべき最善の歴史の記事
$ script/myapp_create.pl controller Books  exists "/root/dev/MyApp/script/../lib/MyApp/Controller"  exists "/root/dev/MyApp/script/../t"  created "/root/dev/MyApp/script/../lib/MyApp/Controller/Books.pm"  created "/root/dev/MyApp/script/../t/controller_Books.t"

Then edit lib/MyApp/Controller/Books.pm and add the following method to the controller:

=head2 list  Fetch all book objects and pass to books/list.tt2 in stash to be displayed  =cut  sub list : Local {  # Retrieve the usual perl OO '$self' for this object. $c is the Catalyst  # 'Context' that's used to 'glue together' the various components  # that make up the application  my ($self, $c) = @_;  # Retrieve all of the book records as book model objects and store in the  # stash where they can be accessed by the TT template  $c->stash->{books} = [$c->model('MyAppDB::Book')->all];  # Set the TT template to use.  You will almost always want to do this  # in your action methods (action methods respond to user input in  # your controllers).  $c->stash->{template} = 'books/list.tt2';  }

Note: Programmers experienced with object-oriented Perl should recognize $self as a reference to the object where this method was called. On the other hand, $c will be new to many Perl programmers who have not used Catalyst before (it's sometimes written as $context). The Context object is automatically passed to all Catalyst components. It is used to pass information between components and provide access to Catalyst and plugin functionality.

TIP: You may see the $c->model('MyAppDB::Book') used above written as $c->model('MyAppDB')->resultset('Book). The two are equivalent.

Note: Catalyst actions are regular Perl methods, but they make use of Nicholas Clark's attributes module (that's the : Local next to the sub list in the code above) to provide additional information to the Catalyst dispatcher logic.

CATALYST VIEWS

Views are where you render output, typically for display in the user's web browser, but also possibly using other display output-generation systems. As with virtually every aspect of Catalyst, options abound when it comes to the specific view technology you adopt inside your application. However, most Catalyst applications use the Template Toolkit, known as TT (for more information on TT, see http://www.template-toolkit.org). Other popular view technologies include Mason ( and http://www.masonbook.com) and HTML::Template (

Create a Catalyst View Using TTSite

When using TT for the Catalyst view, there are two main helper scripts:

  • Catalyst::Helper::View::TT
  • Catalyst::Helper::View::TTSite

Both are similar, but TT merely creates the lib/MyApp/View/TT.pm file and leaves the creation of any hierarchical template organization entirely up to you. (It also creates a t/view_TT.t file for testing; test cases will be discussed in Part 7). The TTSite helper creates a modular and hierarchical view layout with separate Template Toolkit (TT) files for common header and footer information, configuration values, a CSS stylesheet, and more.

While TTSite is useful to bootstrap a project, we recommend that unless you know what your're doing or want to pretty much use the supplied templates as is, that you use the plain Template Toolkit view when starting a project from scratch. This is because TTSite can be tricky to customize. Additionally TT contains constructs that you need to learn yourself if you're going to be a serious user of TT. Our experience suggests that you're better off learning these from scratch. We use TTSite here precisely because it is useful for bootstrap/prototype purposes.

Enter the following command to enable the TTSite style of view rendering for this tutorial:

$ script/myapp_create.pl view TT TTSite  exists "/root/dev/MyApp/script/../lib/MyApp/View"  exists "/root/dev/MyApp/script/../t"  created "/root/dev/MyApp/script/../lib/MyApp/View/TT.pm"  created "/root/dev/MyApp/script/../root/lib"  ...  created "/root/dev/MyApp/script/../root/src/ttsite.css"

This puts a number of files in the root/lib and root/src directories that can be used to customize the look and feel of your application. Also take a look at lib/MyApp/View/TT.pm for config values set by the TTSite helper.

TIP: Note that TTSite does one thing that could confuse people who are used to the normal TT Catalyst view: it redefines the Catalyst context object in templates from its usual c to Catalyst. When looking at other Catalyst examples, remember that they almost always use c. Note that Catalyst and TT do not complain when you use the wrong name to access the context object…TT simply outputs blanks for that bogus logic (see next tip to change this behavior with TT DEBUG options). Finally, be aware that this change in name only applies to how the context object is accessed inside your TT templates; your controllers will continue to use $c (or whatever name you use when fetching the reference from @_ inside your methods). (You can change back to the "default" behavior be removing the CATALYST_VAR line from lib/MyApp/View/TT.pm, but you will also have to edit root/lib/config/main and root/lib/config/url. If you do this, be careful not to have a collision between your own c variable and the Catalyst c variable.)

TIP: When troubleshooting TT it can be helpful to enable variable DEBUG options. You can do this in a Catalyst environment by adding a DEBUG line to the __PACKAGE__-config> declaration in lib/MyApp/View/TT.pm:

__PACKAGE__->config({  CATALYST_VAR => 'Catalyst',  ...  DEBUG        => 'undef',  ...  });

There are a variety of options you can use, such as 'undef', 'all', 'service', 'context', 'parser', 'provider', and 'service'. See Template::Constants for more information (remove the DEBUG_ portion of the name shown in the TT docs and convert to lower case for use inside Catalyst).

NOTE: Please be sure to disable TT debug options before continuing the tutorial (especially the 'undef' option — leaving this enabled will conflict with several of the conventions used by this tutorial and TTSite to leave some variables undefined on purpose).

Using RenderView for the Default View

Once your controller logic has processed the request from a user, it forwards processing to your view in order to generate the appropriate response output. Catalyst v5.7000 ships with a new mechanism, Catalyst::Action::RenderView, that automatically performs this operation. If you look in lib/MyApp/Controller/Root.pm, you should see the empty definition for the sub end method:

sub end : ActionClass('RenderView') {}

The following bullet points provide a quick overview of the RenderView process:

  • Root.pm is designed to hold application-wide logic.
  • At the end of a given user request, Catalyst will call the most specific end method that's appropriate. For example, if the controller for a request has an end method defined, it will be called. However, if the controller does not define a controller-specific end method, the "global" end method in Root.pm will be called.
  • Because the definition includes an ActionClass attribute, the Catalyst::Action::RenderView logic will be executed after any code inside the definition of sub end is run. See Catalyst::Manual::Actions for more information on ActionClass.
  • Because sub end is empty, this effectively just runs the default logic in RenderView. However, you can easily extend the RenderView logic by adding your own code inside the empty method body ({}) created by the Catalyst Helpers when we first ran the catalyst.pl to initialize our application. See Catalyst::Action::RenderView for more detailed information on how to extended RenderView in sub end.

The History Leading Up To RenderView

Although RenderView strikes a nice balance between default behavior and easy extensibility, it is a new feature that won't appear in most existing Catalyst examples. This section provides some brief background on the evolution of default view rendering logic with an eye to how they can be migrated to RenderView:

  • Private end Action in Application ClassOlder Catalyst-related documents often suggest that you add a "private end action" to your application class (MyApp.pm) or Root.pm (MyApp/Controller/Root.pm). These examples should be easily converted to RenderView by simply adding the attribute :ActionClass('RenderView') to the sub end definition. If end sub is defined in your application class (MyApp.pm), you should also migrate it to MyApp/Controller/Root.pm.
  • Catalyst::Plugin::DefaultEndDefaultEnd represented the "next step" in passing processing from your controller to your view. It has the advantage of only requiring that DefaultEnd be added to the list of plugins in lib/MyApp.pm. It also allowed you to add "dump_info=1″ (precede with "?" or "&" depending on where it is in the URL) to force the debug screen at the end of the Catalyst request processing cycle. However, it was more difficult to extend than the RenderView mechanism, and is now deprecated.
  • Catalyst::Action::RenderViewAs discussed above, the current recommended approach to handling your view logic relies on Catalyst::Action::RenderView. Although similar in first appearance to the "private end action" approach, it utilizes Catalyst's "ActionClass" mechanism to provide both automatic default behavior (you don't have to include a plugin as with DefaultEnd) and easy extensibility. As with DefaultEnd, it allows you to add "dump_info=1″ (precede with "?" or "&" depending on where it is in the URL) to force the debug screen at the end of the Catalyst request processing cycle.

It is recommended that all Catalyst applications use or migrate to the RenderView approach.

Globally Customize Every View

When using TTSite, files in the subdirectories of root/lib can be used to make changes that will appear in every view. For example, to display optional status and error messages in every view, edit root/lib/site/layout, updating it to match the following (the two HTML span elements are new):

  
[% status_msg %] [% error_msg %] [% content %]

If we set either message in the Catalyst stash (e.g., $c->stash->{status_msg} = 'Request was successful!') it will be displayed whenever any view used by that request is rendered. The message and error CSS styles are automatically defined in root/src/ttsite.css and can be customized to suit your needs.

Note: The Catalyst stash only lasts for a single HTTP request. If you need to retain information across requests you can use Catalyst::Plugin::Session (we will use Catalyst sessions in the Authentication part of the tutorial).

Create a TT Template Page

To add a new page of content to the TTSite view hierarchy, just create a new .tt2 file in root/src. Only include HTML markup that goes inside the HTML and tags, TTSite will use the contents of root/lib/site to add the top and bottom.

First create a directory for book-related TT templates:

$ mkdir root/src/books

Then create root/src/books/list.tt2 in your editor and enter:


[% # This is a TT comment.  The '-' at the end "chomps" the newline.  You won't -%]  [% # see this "chomping" in your browser because HTML ignores blank lines, but  -%]  [% # it WILL eliminate a blank line if you view the HTML source.  It's purely   -%]  [%- # optional, but both the beginning and the ending TT tags support chomping. -%]  [% # Provide a title to root/lib/site/header -%]  [% META title = 'Book List' -%]    [% # Display each book in a table row %]  [% FOREACH book IN books -%]    [% END -%]  
TitleRatingAuthor(s)
[% book.title %] [% book.rating %] [% # First initialize a TT variable to hold a list. Then use a TT FOREACH -%] [% # loop in 'side effect notation' to load just the last names of the -%] [% # authors into the list. Note that the 'push' TT vmethod does not -%] [% # a value, so nothing will be printed here. But, if you have something -%] [% # in TT that does return a method and you don't want it printed, you -%] [% # can: 1) assign it to a bogus value, or 2) use the CALL keyword to -%] [% # call it and discard the return value. -%] [% tt_authors = [ ]; tt_authors.push(author.last_name) FOREACH author = book.authors %] [% # Now use a TT 'virtual method' to display the author count in parens -%] ([% tt_authors.size %]) [% # Use another TT vmethod to join & print the names & comma separators -%] [% tt_authors.join(', ') %]

As indicated by the inline comments above, the META title line uses TT's META feature to provide a title to root/lib/site/header. Meanwhile, the outer FOREACH loop iterates through each book model object and prints the title and rating fields. An inner FOREACH loop prints the last name of each author in a comma-separated list within a single table cell.

If you are new to TT, the [% and %] tags are used to delimit TT code. TT supports a wide variety of directives for "calling" other files, looping, conditional logic, etc. In general, TT simplifies the usual range of Perl operators down to the single dot (.) operator. This applies to operations as diverse as method calls, hash lookups, and list index values (see http://www.template-toolkit.org/docs/default/Manual/Variables.html for details and examples). In addition to the usual Template module Pod documentation, you can access the TT manual at http://www.template-toolkit.org/docs/default/.

NOTE: The TTSite helper creates several TT files using an extension of .tt2. Most other Catalyst and TT examples use an extension of .tt. You can use either extension (or no extension at all) with TTSite and TT, just be sure to use the appropriate extension for both the file itself and the $c->stash->{template} = … line in your controller. This document will use .tt2 for consistency with the files already created by the TTSite helper.

RUN THE APPLICATION

First, let's enable an environment variable option that causes DBIx::Class to dump the SQL statements it's using to access the database (this option can provide extremely helpful troubleshooting information):

$ export DBIC_TRACE=1

NOTE: You can also use the older export DBIX_CLASS_STORAGE_DBI_DEBUG=1, but that's a lot more to type.

This assumes you are using BASH as your shell — adjust accordingly if you are using a different shell (for example, under tcsh, use setenv DBIX_CLASS_STORAGE_DBI_DEBUG 1).

NOTE: You can also set this in your code using $class->storage->debug(1);. See DBIx::Class::Manual::Troubleshooting for details (including options to log to file instead of displaying to the Catalyst development server log).

Then run the Catalyst "demo server" script:

$ script/myapp_server.pl

Your development server log output should display something like:

$ script/myapp_server.pl  [debug] Debug messages enabled  [debug] Loaded plugins:  .----------------------------------------------------------------------------.  | Catalyst::Plugin::ConfigLoader  0.13                                       |  | Catalyst::Plugin::StackTrace  0.06                                         |  | Catalyst::Plugin::Static::Simple  0.14                                     |  '----------------------------------------------------------------------------'  [debug] Loaded dispatcher "Catalyst::Dispatcher"  [debug] Loaded engine "Catalyst::Engine::HTTP"  [debug] Found home "/home/me/MyApp"  [debug] Loaded Config "/home/me/myapp.yml"  [debug] Loaded components:  .-----------------------------------------------------------------+----------.  | Class                                                           | Type     |  +-----------------------------------------------------------------+----------+  | MyApp::Controller::Books                                        | instance |  | MyApp::Controller::Root                                         | instance |  | MyApp::Model::MyAppDB                                           | instance |  | MyApp::Model::MyAppDB::Author                                   | class    |  | MyApp::Model::MyAppDB::Book                                     | class    |  | MyApp::Model::MyAppDB::BookAuthor                               | class    |  | MyApp::View::TT                                                 | instance |  '-----------------------------------------------------------------+----------'  [debug] Loaded Private actions:  .----------------------+--------------------------------------+--------------.  | Private              | Class                                | Method       |  +----------------------+--------------------------------------+--------------+  | /default             | MyApp::Controller::Root              | default      |  | /end                 | MyApp::Controller::Root              | end          |  | /books/index         | MyApp::Controller::Books             | index        |  | /books/list          | MyApp::Controller::Books             | list         |  '----------------------+--------------------------------------+--------------'  [debug] Loaded Path actions:  .-------------------------------------+--------------------------------------.  | Path                                | Private                              |  +-------------------------------------+--------------------------------------+  | /books/list                         | /books/list                          |  '-------------------------------------+--------------------------------------'  [info] MyApp powered by Catalyst 5.7002  You can connect to your server at http://localhost:3000

Some things you should note in the output above:

  • Catalyst::Model::DBIC::Schema took our MyAppDB::Book and made it MyApp::Model::MyAppDB::Book (and similar actions were performed on MyAppDB::Author and MyAppDB::BookAuthor).
  • The "list" action in our Books controller showed up with a path of /books/list.

Point your browser to http://localhost:3000 and you should still get the Catalyst welcome page.

Next, to view the book list, change the URL in your browser to http://localhost:3000/books/list. You should get a list of the five books loaded by the myapp01.sql script above, with TTSite providing the formatting for the very simple output we generated in our template. The count and space-separated list of author last names appear on the end of each row.

Also notice in the output of the script/myapp_server.pl that DBIC used the following SQL to retrieve the data:

SELECT me.id, me.title, me.rating FROM books me

Along with a list of the following commands to retrieve the authors for each book (the lines have been "word wrapped" here to improve legibility):

SELECT author.id, author.first_name, author.last_name  FROM book_authors me  JOIN authors author ON ( author.id = me.author_id )  WHERE ( me.book_id = ? ): `1'

You should see 5 such lines of debug output as DBIC fetches the author information for each book.

USING THE DEFAULT TEMPLATE NAME

By default, Catalyst::View::TT will look for a template that uses the same name as your controller action, allowing you to save the step of manually specifying the template name in each action. For example, this would allow us to remove the $c->stash->{template} = 'books/list.tt2′; line of our list action in the Books controller. Open lib/MyApp/Controller/Books.pm in your editor and comment out this line to match the following (only the $c->stash->{template} line has changed):

=head2 list  Fetch all book objects and pass to books/list.tt2 in stash to be displayed  =cut  sub list : Local {  # Retrieve the usual perl OO '$self' for this object. $c is the Catalyst  # 'Context' that's used to 'glue together' the various components  # that make up the application  my ($self, $c) = @_;  # Retrieve all of the book records as book model objects and store in the  # stash where they can be accessed by the TT template  $c->stash->{books} = [$c->model('MyAppDB::Book')->all];  # Set the TT template to use.  You will almost always want to do this  # in your action methods (actions methods respond to user input in  # your controllers).  #$c->stash->{template} = 'books/list.tt2';  }

Catalyst::View::TT defaults to looking for a template with no extension. In our case, we need to override this to look for an extension of .tt2. Open lib/MyApp/View/TT.pm and add the TEMPLATE_EXTENSION definition as follows:

__PACKAGE__->config({  CATALYST_VAR => 'Catalyst',  INCLUDE_PATH => [  MyApp->path_to( 'root', 'src' ),  MyApp->path_to( 'root', 'lib' )  ],  PRE_PROCESS  => 'config/main',  WRAPPER      => 'site/wrapper',  ERROR        => 'error.tt2',  TIMER        => 0,  TEMPLATE_EXTENSION => '.tt2',  });

You should now be able to restart the development server as per the previous section and access the http://localhost:3000/books/list as before.

NOTE: Please note that if you use the default template technique, you will not be able to use either the $c->forward or the $c->detach mechanisms (these are discussed in Part 2 and Part 8 of the Tutorial).

RETURN TO A MANUALLY-SPECIFIED TEMPLATE

In order to be able to use $c->forward and $c->detach later in the tutorial, you should remove the comment from the statement in sub list:

$c->stash->{template} = 'books/list.tt2';

Then delete the TEMPLATE_EXTENSION line in lib/MyApp/View/TT.pm.

You should then be able to restart the development server and access http://localhost:3000/books/list in the same manner as with earlier sections.

Kennedy Clark, hkclark [a] gmail.com

Kennedy Clark, hkclark [a] gmail.com

Please report any errors, issues or suggestions to the author. The most recent version of the Catalyst Tutorial can be found at http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst-Manual/lib/Catalyst/Manual/Tutorial/.

Please report any errors, issues or suggestions to the author. The most recent version of the Catalyst Tutorial can be found at http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst-Manual/lib/Catalyst/Manual/Tutorial/.

Copyright 2006, Kennedy Clark, under Creative Commons License (

Copyright 2006, Kennedy Clark, under Creative Commons License (



These are our most popular posts:

日本HP - HP ProLiant サーバー - SATAハードディスクとSAS ...

2007年12月23日 ... PATAよりSATAのが安いのでは) ... ちゃんと探せばミドルレンジのSATAが1万円で お釣りがくるはずです。 .... グラフィックボードのお話大変参考になりました、ほとんど3D は必要としないので8600GTSは欲しい方に譲って、アドバイスを参考に ... read more

記事まとめ : Ψ(`∀´)Ψケケケ と (´・ω・`)ショボーン

つまり、ハーバード大学のアドミッション・コミティー(入学を協議する委員会)は、学資 援助などの必要の有無や学資援助の額の大きさに関わらず、最も優れた学生を ... SAT I およびSAT IIのサブジェクトテストで、650点から800点の得点を有する志願者の合格 率は高まります。 ... 英語を母国語としない学生は、英語力を証明しなければなりません 。 read more

Harvard Club of Japan

ハードディスクドライブはその構造上機械的な動作部位を持っており、高可用性を必要と するミッションクリティカルなシステムへの要求に応えるために ... SATA、SASは本来 信号インターフェイスの違いであり、機械的な部品としての信頼性に直接影響するもの ではありません。 .... この期間データが消失しないことをお約束するものではありません。 read more

不思議な構成のBTOパソコンを買ってしまいこまっています - BIGLOBE ...

大学の数学というのは専門分野で言えば日本語と同じような位置付けにあるわけです、 しかし一方では特に必要としない人も大勢います。 線形代数や微分積分の必要性や その有用性について議論したい人がそのような人々にあたります。 read more

0 件のコメント:

コメントを投稿