The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
=encoding utf8

=head1 題名

Jifty::Manual::Tutorial_ja - あっという間にゼロからJifty

=head1 説明

このチュートリアルを読めば、Jiftyではじめてのアプリケーションを構築するにあたって知っておくべきことはすべてわかるはずです。

=cut

=head1 使い方

=head2 必要なもの

ここでは――少なくともこのチュートリアルの執筆時点で――インストールしておくべきものを紹介します。

=head2 Jiftyのインストール

そんなに構えなくても大丈夫。私たちはDRY (Don't Repeat Yourself) の原則をとても大事に思っていますし、だからこそPerlやCPANを愛しているのですから。JiftyはCPANのすばらしいコードをたくさん利用しています。直接依存しているCPANパッケージは全部あわせて100にもなりましたが、そのほとんどはクロス・プラットフォームなピュアPerlパッケージですから、Perlを利用できるプラットフォームならインストールするだけでばっちり動くはずです。

それだけではありません。次から次へとライブラリをダウンロードするだけで一日が終わってしまわないよう、バンドルできるライブラリはすべてJiftyパッケージのなかにまとめるようにしています。Jiftyのインストーラはシステムに必要なモジュールを調べて一気にダウンロード、インストールできるようになっています。でも、ご心配なく。システムの構成を変更する前にはまずみなさんの確認を取るようになっていますから。

ほとんどのシステムでは、PerlにバンドルされているCPANモジュールを使えばJiftyをダウンロードしてインストールできます。

  # perl -MCPAN -e'install Jifty'

JiftyのC<.tar.gz>をダウンロードしてきた場合は手動でインストールすることもできます。

  # tar xzvf jifty-<version>.tgz
  # cd jifty-<version>
  # perl Makefile.PL
  # make
  # make test
  # make install

テストが通らないようでしたら、お話を聞きたいので、C<jifty-devel@lists.jifty.org>に参加して失敗したことを報告してください(メーリング・リストへの参加方法については以下の「L</困ったときは>」をご覧ください)。

=head2 足場をつくる(スキャフォールディング)

Jiftyをうまくインストールできたら、準備完了。はじめてのアプリケーションをつくってみましょう。

アプリケーションを走らせるにあたって、「本当に」必要なのはF<jifty>というコマンドラインツールのみです(新しくつくったアプリケーションのF<bin/>ディレクトリに入っています)。

もちろんふつうはもう少しディレクトリやファイルを用意しておいた方が作業が楽になります。Jiftyにはそのような構造を構築するツールもついてきます。

どこか、新しいJiftyアプリケーションをつくってもかまわないディレクトリに移動してください(Jiftyはサブディレクトリをつくります)。

  # jifty app --name MyWeblog
  Creating new application MyWeblog
  Creating directory MyWeblog/lib
  Creating directory MyWeblog/lib/MyWeblog
  Creating directory MyWeblog/bin
  Creating directory MyWeblog/etc
  Creating directory MyWeblog/doc
  Creating directory MyWeblog/log
  Creating directory MyWeblog/var
  Creating directory MyWeblog/var/mason
  Creating directory MyWeblog/share
  Creating directory MyWeblog/share/po
  Creating directory MyWeblog/share/web
  Creating directory MyWeblog/share/web/templates
  Creating directory MyWeblog/share/web/static
  Creating directory MyWeblog/lib/MyWeblog/Model
  Creating directory MyWeblog/lib/MyWeblog/Action
  Creating directory MyWeblog/t
  Creating configuration file MyWeblog/etc/config.yml

では、ひとつひとつ見ていきましょう。

=over

=item lib

F<lib/>はみなさんのアプリケーションのコードを入れるところです。アプリケーションはふつういくつかのクラスで構成されます。

=item bin

F<bin/>のなかにはF<jifty>というコマンド・ディスパッチャが入っています。特に重要なコマンドとしては、データベースのスキーマを設定したり更新したりするC<schema>と、スタンドアロンのウェブサーバを起動するC<server>があります。F<jifty>にどのようなコマンドがあるか知りたい場合は次のようにタイプしてください。

    jifty help

=item etc

F<etc/>には設定ファイルが入ります。設定ファイルがない場合はJiftyが適切なデフォルト値を用意します。

=item doc

いかにJiftyの魔法でもドキュメントまでは書いてはくれませんが、「みなさんが」ドキュメントを書くときはF<doc/>に入れてください。

=item log

JiftyはL<Log::Log4perl>を使ってログの設定を行います。デフォルトではF<log>ディレクトリにF<server.log>とF<error.log>というログを吐き出します。

=item var

Jiftyはサーバが走っている間はここにキャッシュファイルを保管します。このディレクトリにはいっさい手を触れる必要はありません。

=item share/web/po

Jiftyは国際化にも対応しています。翻訳("portable object templates")はF<share/web/po/>に入れてください。

=item share/web/templates

モダンなJiftyアプリケーションのテンプレートとしてはL<Template::Declare>をおすすめしていますが、L<HTML::Mason>のテンプレートもサポートしています。MasonのテンプレートはF<share/web/templates/>に入れてください。Jiftyに最初からついてくるアプリケーションの「ひな形」もF<share/web/templates/>にインストールされます。このデフォルトアプリケーションは、基本的なアプリケーションを手っ取り早くつくるときには便利ですが、アプリケーションが進化していくにつれてカスタマイズが必要になっていくことでしょう。

PerlがどこにJiftyのデフォルト・テンプレートをインストールしたか知りたい場合は次のようにします。

  perl -MJifty::Util -e 'print Jifty::Util->share_root'

=item share/web/static

ウェブ・アプリケーションが提供するコンテンツのなかには、テンプレート・エンジンを通す必要のない(あるいは「通すべきでない」)ものも少なからずあります。

そのような静的ファイルについては、F<share/web/static/>に入れておいてください。適切な名前のテンプレートがない場合は静的ファイルがサーブされます。

また、Jiftyには最初からCSSのスタイルシート、Javascriptライブラリ、Ponyがついてきます。JiftyディストリビューションのF<share/web/static>のなか、あるいはJiftyがデフォルトテンプレートをインストールした場所をご覧ください。

=item lib/MyWebLog/Model

アプリケーションの本当の基礎となるものはC<lib/MyWeblog/Model>に入っています。ここに入っているクラスはアプリケーションのデータ構造とそれらの相関関係を定義するものです。Jiftyはこのモデル・クラスを利用して必要なときにデータベースのスキーマを設定・更新します。

Jiftyのオブジェクトモデルの詳細についてはL<Jifty::Manual::ObjectModel>をご覧ください。

=item lib/MyWebLog/Action

アクションはモデル・クラスに対するAPIです。ある意味アクションはHTMLフォームだと思われるかもしれませんが、それをもっと一般化したものです。JiftyはみなさんのB<モデル>に対して基本的なデータベース操作(C<CREATE>, C<READ>, C<UPDATE>, C<DELETE>)を行うB<アクション>を動的に生成します。

=item t

Jiftyはアプリケーションの土台を一式用意しますが、まだあらゆるテストを用意することまではできません(もっとも、生成したモデル・クラスに対する簡単なテストは用意します)。

=back

=head2 データ・モデルを構築する

このチュートリアル・アプリケーションの名前がB<MyWebLog>であることからも想像がつくかと思いますが、ここでは例題として簡単なウェブログ・アプリケーションをとりあげます。今後のチュートリアルでは、認証やコメント、RSSやAtomフィードの機能を追加する予定です。

=head3 記事

ウェブログの中心はふつう記事です。だから、当然最初につくるモデルはC<post>になります。

  # cd MyWeblog
  # jifty model --name Post
  Writing file /tmp/MyWeblog/lib/MyWeblog/Model/Post.pm
  Writing file /tmp/MyWeblog/t/00-model-Post.t

すごいですね! これでB<Post>というモデルができたのです(もっとも、いまのところモデルらしいことはしませんけれどね)。

お好きなエディタでF<lib/MyWeblog/Model/Post.pm>を開いてください。

このような画面になるはずです。

  use strict;
  use warnings;
  
  package MyWeblog::Model::Post;
  use Jifty::DBI::Schema;
  
  use MyWeblog::Record schema {
  
  };
  
  # Your model-specific methods go here.
  
  1;

では、このモデル・クラスに記事の構造を教えましょう。まずは記事にC<body>とC<title>を用意します(将来的にはC<category>を追加したり、C<category>をC<tags>テーブルにアップグレードして、完全なフォークソノミー対応にする予定です)。

カーソルを以下の行のすぐ下に移動してください。

  use MyWeblog::Record schema {

以下の行を加えます。

  column title =>
        type is 'text',
        label is 'Title',
        default is 'Untitled post';

  column body => 
        type is 'text',
        label is 'Content',
        render_as 'Textarea';

モデル・クラスを保存しましょう。

=head2 Jiftyのアプリケーション・サーバを起動する

これで簡単ながら動作するアプリケーションができました。C<jifty server>とタイプしてウェブサーバを起動して見てみましょう。

最初に目にするのは、Jiftyはデータベースがないことに気がついたので用意します、というメッセージでしょう。Jiftyは、デフォルトではSQLiteデータベースを使ってアプリケーションをセットアップします。PostgreSQLやMySQLを使いたい場合はF<etc/config.yml>に多少設定を追加する必要があります(L<Jifty::Config>にもう少し詳しい説明があります)。

    # jifty server
    WARN - Application schema has no version in the database.
    WARN - Automatically creating your database.
    INFO - Generating SQL for application MyWeblog...
    INFO - Using MyWeblog::Model::Post, as it appears to be new.
    INFO - Using Jifty::Model::Session, as it appears to be new.
    INFO - Using Jifty::Model::Metadata, as it appears to be new.
    INFO - Set up version 0.0.1, jifty version 0.81208
    INFO - You can connect to your server at http://localhost:8888/

最後の行以外はデータベースの設定についての情報です。これはJiftyがデータベースを変更したときにしか表示されません。

最後の行には、ブラウザで表示するときのURLが書いてあります。試しに見てみてください。AJAXのきいた管理UIやオンラインドキュメントブラウザ、Ponyをお見逃しなく。

プラットフォームによっては"./bin/jifty server"とタイプする必要があるかもしれません。

=head2 ユーザ・インタフェースの構築

管理画面を使えばアプリケーションのデータを管理するのに必要なものはすべて手に入ります。エントリを追加したり更新したり削除したりもできるのですが、それではあまりウェブログらしくはありません。

=head3 記事を投稿する

まずは新しいエントリを投稿するページをつくりましょう。

エディタで新しくF<lib/MyWeblog/View.pm>というファイルを開いて、このようにしてください。

  package MyWeblog::View;
  use strict;
  use warnings;
  use Jifty::View::Declare -base;
  
  template post => page { title => 'Post Entry' } content {
      my $action = new_action(class => 'CreatePost');
  
      form {
          render_action $action;
          form_submit(label => 'Post');
      }
  };
  
  1;

=head3 閲覧する

「基本的な」エントリ一覧をつくるのは本当に簡単です。AJAXでページングするきれいな一覧の方はもう少し複雑ですが、ここでは両方のやり方を紹介します。お好みの方を選んでください。

=head4 手っ取り早いやり方

F<lib/MyWeblog/View.pm>を開いて、C<post>テンプレートとファイル末尾の"1;"の間にこのようなコードを追加してください。

  template '/' => page {
      # Get all posts.
      my $posts = MyWeblog::Model::PostCollection->new;
      $posts->unlimit;
  
      # Display each post in a <dl>.
      dl {
          while (my $post = $posts->next) {
              dt { $post->title }
              dd { $post->body  }
          }
      }
  };

これでC<http://localhost:8888>に行くと、すべてのエントリが迎えてくれるようになります。

=head4 複雑だけどクールなツールをふんだんに使う方法

「複雑な方法」ではJiftyの上級機能のひとつである「ページ領域(Page regions)」というものを使います。領域を指定しておくと、最近の高性能なブラウザならAJAXで、C<lynx>やC<w3m>のように機能が限定されたブラウザでも通常のGETリクエストを使って、ページの一部だけを独立してリロードすることができます。

このアプローチの欠点は、指定する領域ごとに固有のテンプレートを用意しなければならないことです。でも、うれしいことに、これは領域の問題を抜きにしてもよいデザインの仕方といえます。

複雑な方法も、最初は簡単な方法と同じです。F<lib/MyWeblog/View.pm>の'/'テンプレートをこのようなコードで置き換えてください(シンプルにしてしまうのが怖ければ追加しても結構です)。

  template '/' => page {
      render_region(
          name => 'myweblog-posts',
          path => '/fragments/page_of_posts',
      );
  };

勘のいい方ならたぶんもうおわかりでしょうが、今度はF<lib/MyWeblog/View.pm>の中にC</fragments/page_of_posts>というテンプレートをつくる必要があります。このようにしてください。

  template '/fragments/page_of_posts' => sub {
      # Retrieve the current page argument, defaulting to 1.
      my $page = get('page') || 1;
      
      # Get all posts.
      my $posts = MyWeblog::Model::PostCollection->new;
      $posts->unlimit;
      
      # Display up to three posts on the current page.
      $posts->set_page_info(
          current_page => $page,
          per_page     => 3,
      );
  
      # Notify the user what page they're on if there are multiple.
      if ($posts->pager->last_page > 1) {
          p { "Page $page of " . $posts->pager->last_page }
      }
  
      # Display the current page of posts.
      dl {
          attr { class => 'list' };
  
          while (my $post = $posts->next) {
              dt { $post->title }
              dd { $post->body  }
          }
      };
  
      # Previous page link, the 'page' argument here will set a new value when
      # this region is invoked again.
      if ($posts->pager->previous_page) {
          hyperlink(
              label => 'Previous Page',
              onclick => {
                  args => {
                      page => $posts->pager->previous_page,
                  },
              },
          );
      }
  
      # Next page link.
      if ($posts->pager->next_page) {
          hyperlink(
              label => 'Next Page',
              onclick => {
                  args => {
                      page => $posts->pager->next_page,
                  },
              },
          );
      }
  };

さて、もう一度Jiftyのウェブサーバを起動してみましょう。ブラウザでC</post>を表示して、3つ以上記事を作成してみてください。トップページに戻って、AJAXの利いたC<Next Page>とC<Previous Page>というリンクがあることもチェックしましょう。Javascriptを切るか、C<lynx>で見てみれば、AJAXが自動的にふつうのページの読み込みに変わる様子が確認できます。これだけできて無料なのですから、ありがたいことですね!

=head3 ところで、そのクラスはどこから来たの?

C<MyWeblog::Model::PostCollection>というクラスを見て、あれっと思われた方もいるかもしれません。F<PostCollection.pm>というファイルは存在しないからです。JiftyはC<Jifty::ClassLoader>を使ってさまざまなクラスを自動的に生成しています。もちろんお好みとあればこれらの定義をオーバーライドすることもできます。詳しくはL<Jifty::ClassLoader>をご覧ください。

=head2 ナビゲーション

当然のことながら、投稿ページのURLを覚えていなければならないというのはいささか面倒なことです。メニューに「投稿」ボタンを用意するには、デフォルトのメニューをオーバーライドしなければなりません。

ここではウェブログにディスパッチャを設定しましょう。ディスパッチャは、リクエストされたURLに応じて「なにをするか」を決めるものです。「テンプレートをレンダリングする前」という規則を追加すれば追加のメニューを設定できます。

F<lib/MyWeblog/Dispatcher.pm>というファイルを新たに開いて、この内容を貼り付けてください。

  package MyWeblog::Dispatcher;
  use strict;
  use warnings;
  use Jifty::Dispatcher -base;
  
  before '*' => run {
      my $top = Jifty->web->navigation;
      $top->child(Home => url => '/');
      $top->child(Post => url => '/post', label => 'Post Article');
  };
  
  1;

メニューシステムの詳細はL<Jifty::Web::Menu>をご覧ください。

=head2 おしまい!

おおよそこれだけ知っていればJiftyアプリケーションの構築は始められるはずです。私たちもJiftyをもっと使いやすく、またこのチュートリアルの「手ごわい部分」をなくすべく鋭意努力しています。

ぜひC<jifty-devel>メーリング・リストに参加して、Jiftyをどう使っているか、使ってみて難しいとか使いづらいと思った点をお知らせください。

=head1 そのほかのチュートリアル

=over 4

=item * データベースの管理について

L<Jifty::Manual::Models>

=item * Jiftyに何かをさせる

L<Jifty::Manual::Actions>

=item * ページ領域の使い方

L<Jifty::Manual::PageRegions>

=item * CSSとJS

L<Jifty::Manual::UsingCSSandJS>,
L<Jifty::Manual::JavaScript>

=item * ウェブサービス

L<Jifty::Manual::TutorialRest>に簡単な概要があります。

=item * 継続 - 「ちょっと行ってきて」

L<Jifty::Manual::Continuations>

=item * アクセス管理とセキュリティ

L<Jifty::Manual::AccessControl>

=item * 本番環境へのデプロイ

L<Jifty::Manual::Deploying>

=item * データベースのアップグレード

L<Jifty::Manual::Upgrading>

=item * 一般的な作業のレシピ

L<Jifty::Manual::Cookbook>

=back

=head1 困ったときは

=head2 オンラインヘルプ

C<jifty>のコマンドラインツールにはヘルプ機能が組み込まれています。

  jifty help

  jifty help <command>

サーバが管理者モードで実行されているときは(設定ファイルにC<AdminMode>がない、または非ゼロになっている場合)、ブラウザで「Online Docs」をクリックすると、モジュールごとの膨大なドキュメント一覧が表示されます。

=head2 メーリング・リストに参加する

C<jifty-devel@lists.jifty.org>ではJiftyをどのように構築するか、何に困っているか等が話し合われています。

メーリング・リストに参加したい方はC<jifty-devel-subscribe@lists.jifty.org>宛にメールを送ってください。

=head2 wikiを見る

wikiもあります!(というか、このwikiがJiftyのメイン・サイトなのです)

L<http://jifty.org/>に来て、書き込みしてみてください。

このwikiは、I<Wifty>というJiftyベースのwikiで運用されています。ソースコードはjiftyのsubversionリポジトリから自由に入手可能です。

=head1 バグを報告する

JiftyのバグはC<jifty-devel@lists.jifty.org>に報告してください。

=head1 翻訳者

石垣憲一 (C<ishigaki_at_cpan.org>)

=cut