MojoliciousでGitHub issue 用のテンプレート作る

この記事は Perl入学式 Advent Calendar 2015 の 5日目の記事です。
こんにちは veryblue です。

昨日は @note103さんの「[Perlビギナーのための文字エンコーディング「超」入門](http://note103.hateblo.jp/entry/2015/12/04/094321)」でした。
エンコーディング理解していないのでこれを機に勉強してみます！

さて本日の記事は、昨年1年間Perl入学式で勉強したことを使って、Markdown管理用のWebアプリケーションを作ってみた
このアプリケーションは、昨年の [Perl入学式 Advent Calendar 2014](http://qiita.com/advent-calendar/2014/perl-entrance) の @tomcha_ さん作 [「ぬか漬のすゝめ」](http://tomcha.hatenablog.jp/entry/2014/12/07/002037) を参考にして作りました。


## 作った背景
弊社では GitHub issue を使って、問題管理や問い合わせ対応をしたりしています。
簡単に投稿でき、issueの状態`Open/Close`で現在対応しないといけない案件が何かが、分かるのでとても便利に利用しています。
とても便利なのですが、投稿するときに決まったテンプレートで投稿したい時があります。
そんな時に[GitHub Issueはテンプレート化で、綺麗に書かせる！](http://qiita.com/yoshimikeisui/items/3e1873e3bf1bbafe8733)を見かけました。
このGitHubの機能を使って便利に投稿できるようにしたことを紹介してようと思います。


# 作り方

作ったものはこちら
https://github.com/veryblue/mojo-md-template/

## 作る前のWebアプリケーションの希望を出します（こんな感じにしたい）
まずは作る前にどんなものを作りたいかシュミレーションをしてみます。

- 一覧から選択できるようにしたい
- 投稿するテンプレートは一度確認してから投稿画面に行きたい
- テンプレートは変更や増減することがあるから、システム内に組み込みたくない
- テンプレートはMarkdownファイル(.md)でファイル管理したい

![step1.png](https://qiita-image-store.s3.amazonaws.com/0/32437/e217c332-fe1b-d602-d22f-cd8054e50a88.png)


## 希望を元に作る機能を書き出してみます
必要な画面と、必要な機能を洗い出していきます。

希望を出しているときに、画面がこんな感じであるといいなーと出していましたので、
以下の2つになりました。

1. 一覧ページ
1. 選択したテンプレートを表示するページ

次に、それぞれのページに必要な機能を考えてみます。
テンプレート用のMarkdownファイルは、`.md`ディレクトリを作ってその中に入れておくようにして、
追加や更新をしやすいようにします。
それぞれのページの必要な機能は以下のようになりました。

1. 一覧ページ
    - ディレクトリ内全部のテンプレートをまとめて一覧にする機能
    - 選択させるためのリンクをつける
1. 選択したテンプレートを表示するページ
    - 選択されたテンプレートを表示する機能
    - GitHub issue へのリンク


図解しないと理解しにくい私ですので、機能の流れなどを絵にしてみます。

![step2.png](https://qiita-image-store.s3.amazonaws.com/0/32437/c5f0cbd4-4e51-8445-6fb2-40484d206d77.png)



## 一覧ページを作る
作る機能は2つ

- ディレクトリ内全部のテンプレートをまとめて一覧にする機能
- 選択させるためのリンクをつける

Mojolicious::Lite での index画面（一覧）では、ファイル名を表示する部分を作ります。
Mojolicious::Lite はPerl入学式の第6回「Webアプリケーション編」で学びます。


全体部分のコード

```pl
# 一覧ページ
get '/' => sub {
  my $self = shift;
  my $files = get_md_list();
  $self->stash(files => $files);
  $self->render('index');
};

# ディレクトリ内のmarkdownファイル名を取得
sub get_md_list{
  chdir("$dir");
  my @mdfiles;

  @mdfiles = glob "*.md"; # .md ファイルのみに限定
  
  return \@mdfiles; # リファレンスで返却
}

@@ index.html.ep
% layout 'default';
% title 'issue templates';
<h1>issue templates</h1>

<ul>
% for my $file (@$files) { # デリファレンスして、ファイル名を取得
  <li><a href="file?md=<%= $file %>"><%= $file %></a></li> # mdをキーにしてファイル名でアクセスさせる
% }
</ul>
```

ファイル名を全部取得するサブルーチンを作り、配列のリファレンスで返却しています。

Perl入学式では第3回で学んだ内容を使っています。
サブルーチンの復習は、[第3回 サブルーチン](https://github.com/perl-entrance-org/workshop-2015-04/blob/master/slide.md#サブルーチンの定義-1)
リファレンスの復習は、[第3回 リファレンスのデリファレンス](https://github.com/perl-entrance-org/workshop-2015-03/blob/master/slide.md#デリファレンス-配列)



## 選択したテンプレートを表示するページ
一覧ページから、ファイル名をキーにしてGETアクセスされます。
キーのパラメータ（ファイル名）を受け取り、そのファイル名のMarkdownファイルを探して表示します。

こちらも作る機能は２つです。

- 選択されたテンプレートを表示する機能
- GitHub issue へのリンク

全体のコード

```pl
use URI::Escape;

# /file?md=hoge.md
get '/file' => sub {
  my $self = shift;
  my $file = $self->param('md'); # md がキー
  my $md = get_md_file($file);
  my $url_md = uri_escape_utf8($$md);
  $self->stash(url_md => $url_md);
  $self->stash(md => $md);
  $self->render('file');
};

# ファイル名を受け取って、markdownテンプレートの中身を読み込む
sub get_md_file{
  my $filename = shift;
  chdir("$dir");

  my $body;
  open(IN, $filename);
  while (my $line = <IN>) {
    $body .= $line;
  }
  
  return \$body;
}

# htmlテンプレート
@@ file.html.ep
% layout 'default';
% title 'templates';
<h1>templates</h1>

# 内容の表示をする
<div style="background: #f5f5f5; padding: 1.5em;">
% my $text = $$md;
% $text =~ s/\n/<br>/g; # ファイル内の改行をHTMLで改行するように正規表現で変換する
%== $text
</div>

# GitHub issue へのリンクを生成する
% my $ibody = $url_md;
<a href="https://github.com/{{user}}/{{repo}}/issues/new?title=test&body=<%= $ibody %>" target="_blank">
create new issue
</a>
```

テンプレートのMarkdownファイルの内容を読み取った後、表示する用と、URLで使用するために変換をしているものに分けています。
これは、GitHub issue のテンプレートとしてアクセスさせるためには、`URLエスケープ`する必要がありますので、2つに分けています。

Perl で URLエスケースするには`URI::Escape`が使えます。
テンプレートの中身には日本語を含んでいますので、`uri_escape_utf8` を利用しています。


## 作ってみて、、、勉強になった

コードのほとんどは、昨年の[ぬか漬のすゝめ](http://tomcha.hatenablog.jp/entry/2014/12/07/002037)を参考に、書いては確認して、動かないから直して～の繰り返しでした。
特にリファレンス部分などは理解したつもりがしていなく、実際に講義でやっているときは違うので、
実際に何か作ってみるのをおススメします！



### webアプリを作るには

Webアプリケーションを作る際は、Webの仕組みや構造を知っていると良いです。
私はこの業界に長いのですが、最近までよくよく理解していなかったので、もったいない事してたなと思ってます。

詳しくはこちらの書籍で勉強するのがおすすめです。
[Webを支える技術 ── HTTP，URI，HTML，そしてREST](http://gihyo.jp/magazine/wdpress/plus/978-4-7741-4204-3)


# まとめ
何か作るとつまずく事が多いけど、動くと楽しいから、まず作ってみませんか？！
作りたいものが無いよーって人も手を動かすとアイディアが出てくるかも？！

今年度のPerl入学式もあと2回になりました！
次回は、サブモジュール化やテスト、最終回はWebアプリケーション編です！
特に最後のWebアプリケーション編は、実際にブラウザで動く画面を作りますのでとても楽しいので、
プログラムに興味がある人はぜひぜひ来てともに学びましょう！

明日の担当は @munepom さんです。大掃除が無事終わっていてステキな記事が期待できるはずです！


# 参考情報
- [ぬか漬のすゝめ](http://tomcha.hatenablog.jp/entry/2014/12/07/002037)
- [GitHub Issueはテンプレート化で、綺麗に書かせる！](http://qiita.com/yoshimikeisui/items/3e1873e3bf1bbafe8733)