Ruby + Sinatra でテンプレートエンジンに Mustache (mustache-sinatra) を使う

## 概要

- Ruby + Sinatra でテンプレートエンジン Mustache を使ってシンプルな Web アプリケーションを動かす

## 構成

- macOS Catalina
- Ruby 2.7.0
- Sinatra 2.0.8.1
- Mustache (mustache 0.99.8 + mustache-sinatra 1.0.1)
- Puma 4.3.1

## ソースコード

### ファイル一覧

```
├── Gemfile
├── app.rb
├── config.ru
└── views
    ├── error.mustache
    └── hello.mustache
```

### Gemfile

Sinatra で Mustache を使うために mustache-sinatra を導入する。

```Gemfile
source 'https://rubygems.org'

gem 'puma'
gem 'sinatra'
gem 'mustache-sinatra'
```

### app.rb

メイン処理をするファイル。

```app.rb
require 'sinatra'
require 'mustache/sinatra'

# 404 Not Found 時の処理
not_found do
  values = {:error_message => 'Page Not Found'}
  mustache :error, :layout => false, :locals => values
end

# エラー発生時の処理
error do
  values = {:error_message => env['sinatra.error'].message}
  mustache :error, :layout => false, :locals => values
end

# メッセージ表示ページの処理
get '/hello/:message' do

  # HTML に埋め込む値
  values = {
    :message   => params['message'],
    :ruby_desc => RUBY_DESCRIPTION
  }

  # HTML を表示
  mustache :hello, :layout => false, :locals => values
end
```

### config.ru

rackup コマンド用に config.ru を用意する。

```config.ru
require './app'
run Sinatra::Application
```

### views/error.mustache

エラーページ用 HTML テンプレート。

```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Error page</title>
</head>
<body>
<p>{{ error_message }}</p>
</body>
</html>
```

### views/hello.mustache

ページ用 HTML テンプレート。

```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello, World!</title>
</head>
<body>
<p>{{ message }}</p>
<p>{{ ruby_desc }}</p>
</body>
</html>
```

## Web サーバを起動

### bundle install で環境を構築

bundle install コマンドで Gemfile に記載してあるパッケージがインストールされて Gemfile.lock ファイルが生成される。

現時点(2020年2月9日現在)で生成される Gemfile.lock ファイルは以下のようになる。

```
GEM
  remote: https://rubygems.org/
  specs:
    mustache (0.99.8)
    mustache-sinatra (1.0.1)
      mustache (<= 0.99.8)
    mustermann (1.1.1)
      ruby2_keywords (~> 0.0.1)
    nio4r (2.5.2)
    puma (4.3.1)
      nio4r (~> 2.0)
    rack (2.2.1)
    rack-protection (2.0.8.1)
      rack
    ruby2_keywords (0.0.2)
    sinatra (2.0.8.1)
      mustermann (~> 1.0)
      rack (~> 2.0)
      rack-protection (= 2.0.8.1)
      tilt (~> 2.0)
    tilt (2.0.10)

PLATFORMS
  ruby

DEPENDENCIES
  mustache-sinatra
  puma
  sinatra

BUNDLED WITH
   2.1.4
```

mustache のバージョンが5年前という古いものになっている。

mustache の最新版は2019年12月にリリースされている。
しかし、mustache-sinatra の最新版は2015年1月にリリースされたバージョン 1.0.1 で、その依存関係で mustache は2014年12月にリリースされたバージョン 0.99.8 になっている。

[mustache\-sinatra \| RubyGems\.org \| コミュニティのGemホスティングサービス](https://rubygems.org/gems/mustache-sinatra/)

> 1.0.1 - January 25, 2015 (9KB)

[mustacheの全バージョン履歴 \| RubyGems\.org \| コミュニティのGemホスティングサービス](https://rubygems.org/gems/mustache/versions)

> 1.1.1 - December 03, 2019 (41.5KB)

> 0.99.8 - December 01, 2014 (42.5KB)

### サーバを起動

```
$ RACK_ENV=production bundle exec rackup -s Puma
Puma starting in single mode...
* Version 4.3.1 (ruby 2.7.0-p0), codename: Mysterious Traveller
* Min threads: 0, max threads: 16
* Environment: production
* Listening on tcp://0.0.0.0:9292
Use Ctrl-C to stop
```

## curl でサーバにアクセス

curl でアクセスして動作確認をする。

```
$ curl -i "http://localhost:9292/hello/こんにちは世界&"
HTTP/1.1 200 OK
Content-Type: text/html;charset=utf-8
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Length: 219

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello, World!</title>
</head>
<body>
<p>こんにちは世界&amp;</p>
<p>ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-darwin19]</p>
</body>
</html>
```

## 参考資料

- [Sinatra: README \(Japanese\)](http://sinatrarb.com/intro-ja.html)
- [mustache/mustache\-sinatra: Mustache support for Sinatra applications](https://github.com/mustache/mustache-sinatra)