Skip to content

Latest commit

 

History

History
240 lines (173 loc) · 8.6 KB

03.md

File metadata and controls

240 lines (173 loc) · 8.6 KB

Nephia入門講座, 第3回目です. 前回は, 「占いアプリ」に必要な機能を, lib/Uranai.pmに実装していきました. 今回は, index.htmluranai.htmlという2つのテンプレートを用意して, 「占いアプリ」をひとまず完成させましょう.

テンプレート

テンプレートは, viewディレクトリの中に格納されています. 初期状態ではindex.htmlというテンプレートが用意されているので, まずはこれを「占いアプリ」向けに編集します.

? my $c = shift;
<html>
<head>
  <link rel="stylesheet" href="/static/style.css" />
  <link rel="shortcut icon" href="/static/favicon.ico" />
  <title><?= $c->{title} ?> - powerd by Nephia</title>
</head>
<body>
  <div class="title">
    <span class="title-label"><?= $c->{title} ?></span>
    <span class="envname"><?= $c->{envname} ?></span>
  </div>

  <div class="content">
    <h2>今日の運勢を占おう!</h2>
    <form action="/uranai">
        <input type="text" name="name">
        <input type="submit" value="占う!">
    </form>
  </div>

  <address class="generated-by">Generated by Nephia</address>
</body>
</html>

こんな感じです. ごくシンプルに, 名前を入力するテキストフォームと, 「占う!」と表示された送信ボタンを配置しています. 送信ボタンがクリックされた場合, /uranaiに対してGETメソッドでアクセスを行います.

この状態でplackupコマンドでアプリを立ちあげてしてブラウザで確認すると, 次のように表示されるはずです.

form

うまくフォームが表示されていますね!

エラーが起きたら...

では, この状態でテキストフォームに適当な値を入れて, 「占う!」ボタンを押すとどうなるでしょうか. /uranaiの実装はlib/Uranai.pmに書いてありますが, まだuranai.htmlのテンプレートが用意できていませんね.

error_trace

「テンプレートファイルuranai.htmlが見つかりません!」というエラーが表示されます.

このように, development環境(plackupに-Eオプションを与えない)だと, このようにエラーのトレースが表示されます. 一方, production環境(plackupに-E productionというオプションを指定)だと,

error

このように, 最小限のエラーだけが表示されます(ちなみに, plackupを動かしているコンソールに出力されるログも, -Eオプションによって変化します).

development環境で出るエラートレースはデバッグに有用ですが, サーバー上でこのような情報が出てしまうと, 脆弱性を発見される情報源になりかねませんので, 気をつけましょう.

uranai.htmlの作成

それでは, view/uranai.htmlを作って行きましょう.

? my $c = shift;
<html>
<head>
  <link rel="stylesheet" href="/static/style.css" />
  <link rel="shortcut icon" href="/static/favicon.ico" />
  <title><?= $c->{title} ?> - powerd by Nephia</title>
</head>
<body>
  <div class="title">
    <span class="title-label"><?= $c->{title} ?></span>
    <span class="envname"><?= $c->{envname} ?></span>
  </div>

  <div class="content">
    <h2><?= $c->{name} ?>さんの今日の運勢は...</h2>
      <?= $c->{result} ?>です!!!!!
  </div>

  <address class="generated-by">Generated by Nephia</address>
</body>
</html>

こんな感じです.

前回, lib/Uranai.pmに実装した/uranaiページへアクセスした際の処理において, 最後はこのようになっていました.

    return {
        template => 'uranai.html',
        name     => $req->param('name'),
        result   => $result,
        title    => config->{appname},
        envname  => config->{envname},
    };

実はこのハッシュが, テンプレートの1行目にある? my $c = shift;によって, $cに格納されています. その為, テンプレートの中で<?= $c->{name} ?><?= $c->{result} ?>といった形で利用できるのです.

テンプレートの記法

さて, ここで改めて, テンプレートの中で使える記法について説明しておきます.

Nephiaがデフォルトで利用するテンプレートエンジン, Text::MicroTemplateでは, テンプレート中の行の先頭に?を付けると, その行はPerlのコードとして処理されます. また, <?= $i ?>このように書くと, 生成するHTMLの中に, $iという変数の中身を埋め込むことができます.

これさえ覚えておけば, 後はPerlで色々と細かい処理をすることができます. 例えば,

  <div class="content">
? for my $i (1..10) {
    <?= $i ?>
? }
  </div>

このように書けば, <?= $i ?>の部分は$iが1から10の間まで繰り返し実行されるので,

  <div class="content">
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
  </div>

テンプレートからはこのようなHTMLが生成され,

1to10

このように表示されます.

動作確認

さあ, テンプレートの実装も終わりました. plackupコマンドで起動して, 動作を確認してみましょう!

localhost:5000にアクセスして, テキストボックスに適当な名前を入力し, 占う!ボタンをクリックすると...

result

出来ましたね! このように, 占いの結果が表示されます. これでひとまず, 占いアプリは完成です.

リダイレクト

もちろん, 占いアプリはこれで完璧, とは言えません. 例えば, テキストボックスに何も入力しない状態で占う!ボタンをクリックしてみると...

no_name

このように表示されてしまいます.

いろいろな対策方法がありますが, 今回はシンプルに, 「テキストボックスが空だったら, /uranaiから/indexにリダイレクトさせる」という方針を取ります. というわけで, lib/Uranai.pmのうち, /uranaiにアクセスした際に処理される部分を, 次のように書き換えます.

path '/uranai' => sub {
    my $req = shift;

    my @results = qw/ 大凶 凶 吉 小吉 中吉 大吉 /;
    my $result = $results[int rand(@results)];

    my $name = $req->param('name');

    if ($name eq '') { # ... (1)
        return res { redirect('/'); }
    }

    return {
        template => 'uranai.html',
        name     => $req->param('name'),
        result   => $result,
        title    => config->{appname},
        envname  => config->{envname},
    };
};

テキストフォームに文字列が入っていない場合, $req->param('name')のような形でアクセスすると, undefではなく空文字('')が返ります. その為, (1)の部分で, テキストフォームから受け取ったデータが空文字かどうかをチェックしています.

        return res { redirect('/'); }

この部分が, 実際にリダイレクトを指示している部分です. redirect('/')で, /にリダイレクトすることを示し, これをresに与えることで, /uranaiから/にリダイレクトすることができます.

実際に動かしてみると, テキストボックスに文字列が入っていた場合/uranaiに遷移して結果を表示し, 何も入力しなかった場合はそのまま/に戻ってくることが確認できるはずです.

さて, resの中には, 他にもbodycontent_type, content_encodingなどを入れることができます. 例えば,

    return res {
        content_type('text/plain');
        content_encoding('utf-8');
        body('foobar');
    }

こんな感じにすると,

text

このようなテキストを表示させることができます.

改造改造, また改造!

今回作った占いアプリは, まだまだ改造の余地があります. 例えば...

  • テキストボックスが空欄だった場合, /にリダイレクトした上で「テキストボックスが空欄です!」と表示させる
  • アクセスするごとに占いの結果が変わるので, その日の間は同じ結果を表示するようにする(結果をキャッシュする)
  • twitterと連携して, 占い結果をツイートできるようにする

...などです.

次回予告

次回の「Nephia入門 (4)」では, テンプレートの機能を使って複雑なデータをテーブルで表示する練習をしてみたいと思います.