Middlemanを使った高速プロトタイピング

#Middlemanを使う
- MiddlemanのコーディングはHaml SCSS(Sass) CoffeeScriptといった拡張メタ言語で行い、それをHTML CSS JavaScriptに トランスクリプトしてブラウザ上で確認するという流れをシームレスに実現するための環境です。
- ***Ruby on Rails*** といったサーバーサイドアプリケーションだと HTML ファイルを物理的に生成はしません。ということは、サイトを見るためには***必ず Web サーバーが必要***になります。
- 一方の Middleman は、静的ファイルを物理的に生成することから ***Web サーバーを必要としないサイト***を作ることができます。
- Ruby 関連のプログラム技術を使って効率的に Web サイトを作る。Middleman は正にサーバーサイドを交えた本実装前のプロトタイピングにうってつけの環境というわけです。

##1 開発環境

|アプリ名|バージョン|
|---|---|
|Ruby|2.0.0-p481|
|Ruby gems|2.0.14|
|Bundler|1.11.2|


##2 インストール(Bundlerを用いる場合は、スキップ)

- 後ほど、Bundlerを用いて作業フォルダ内にMiddlemanのgemをインストールするため、今回はスキップします。
- Bundlerを用いない場合は、以下のコードを実行します。

```bash
gem install middleman
```

##3 サンプルサイトの構築

###3.1 作業ディレクトリの作成と初期化

```bash
# try_middleman ディレクトリを作成
mkdir try_middleman
 
# 作成したディレクトリに移動
cd try_middleman

#Bundlerで作業ディレクトリを初期化
bundle init
```

###3.2 BundlerによるMiddlemanのインストール

- 作業ディレクトリに生成された`Gemfile`を下記のように変更します。

- Gemfile

```ruby
source "https://rubygems.org"

gem "middleman"
```

- その後、`bundle install`コマンドを使って、Middlemanをインストールします。

```bash
bundle install --path vendor/bundle
```

###3.3 Middlemanプロジェクトの作成

- はじめに、Middlemanプロジェクトを作成します。

```bash
bundle exec middleman init .
#全部Yを押す
bundle install --path vendor/bundle
```

###3.4 サーバーを起動します。

```bash
bundle exec middleman server
```

###3.5 http://localhost:4567にアクセスします。

![最初のWebサイト](http://take.ms/UvWue)

##4 サイトのビルド

- `middleman build`コマンドでサイトをビルドします。

```bash
bundle exec middleman build
#      create  build/stylesheets/site.css
#      create  build/images/middleman-logo.svg
#      create  build/javascripts/all.js
#      create  build/index.html
#Project built successfully.
```

![Middlemanのディレクトリ構造](http://take.ms/yD6g7)

##5 (option)RubyMineでコーディングする設定

- メニューバーの`run`->`Edit Configuration`->`+マーク`->`Gem Command`を選択します。
- 下記の通り設定します。

|項目|設定値|補足|
|---|---|---|
|Name|Middleman Development|※なんでも良い|
|Gem name|middleman||
|Executable name|middleman||
|Single instance only|checked|チェックボックスはウィンドウの右上に存在|
|Ruby SDK|Use other SDK and gem: rbenv: 2.0.0-p481||
|BundlerタブのRun the script in context of the bundle(bundle exec)|checked||

- 以上の設定をしておくと、RubyMineメニューの`run`->`Debug Middleman`を押すだけで、Middlemanサーバーが立ち上がり、デバッグできるようになります。

##6 Middlemanにおけるテンプレートレイアウト

![Middlemanにおけるテンプレートレイアウト](http://take.ms/FvQdI)

- テンプレートファイル(コンテンツ) - **sample.html.haml**

個別ページです。基本的にここには固有のコンテンツだけが記述されており、その他には Frontmatter というレイアウトページ固有の情報したいページ固有の情報群があります。**ファイル自体の拡張子はhamlですが、コンパイル後の拡張子をファイル名に含める決まりがあります。**

- レイアウトファイル - **layout.haml**

テンプレートファイルを囲うためのモノです。**囲ったテンプレート（コンテンツ）は= yieldと書かれている箇所に出力**されます。

- パーシャル - **_header.haml_footer.haml**
単独で利用されることがなく、他の**テンプレートファイルやレイアウトファイルにインクルード**されることを前提としたものです。**ファイル名に_を接頭辞としてつける決まり**があります。

###6.1 カスタムレイアウト

- Middleman には**layout.erb というレイアウトファイルが最初から用意**されており、デフォルトで全てのページがこのレイアウトファイルに囲われた状態で出力されます。しかし**ページによっては異なるレイアウトを使用したいというケースも往々にしてある**でしょう。例として custom_layout.haml というのを作ってみます。

- `layouts/custom_layout.haml`

```haml
!!!
%html
  %head
    %title 初めてのカスタムレイアウト
  %body
    .wrapper
      = yield
```

- 次に、`custom.html.haml`ファイルを新規作成し、先ほどのカスタムレイアウトを指定します。
- `---`で囲まれた部分は、***Frontmatter***というものです。YAML形式またはJSON形式のどちらでも記述することができます。ただし、RubyMine上ではエラーとして扱われるため、先頭にバックスラッシュをつけ、`\---`のようにしておく良いです。(生成されるコードは同じものになります。)

- `custom.html.haml`


```haml
---
layout: custom_layout
---

%h1 Custom Layout page.
%p カスタムレイアウトのページです。
```

- プロジェクトの規模が大きくなると、**Frontmatteによる指定はやや冗長で面倒**になります。その場合は **config.rb に以下のようなコードを追記して、テンプレートを一括指定**します。

- `config.rb`に下記を追記

```rb
page "/custom/*", layout: "custom_layout"
```

#6.2 レイアウトの入れ子

- 複数レイアウトを入れ子にして積み重ねることが出来ます。コードの重複を抑えることができ、複雑なレイアウトを作る上で欠かせません。例として以下の様な二種類のレイアウトがあったとします。
- それぞれ、一部の箇所が異なるだけで、**それ以外は同じコード**です。ならばこの**重複している箇所をレイアウトのベースとして切り出し、** `layout_a.haml` `layout_b.haml` が**それぞれベースレイアウトを入れ子で読みこめばコードの重複を解消することができる**わけです。

- `layout_a.haml`

```haml
!!!
%html
  %head
    %meta{charset: 'UTF-8'}
    %title= current_page.data.title || "Middleman"
  %body
    %header.global-header
      %h1 Page title
       
    .contents
      = yield
     
    %footer.global-footer
      %small Soushi Yamamoto
```

- `layout_b.haml`

```haml
!!!
%html
  %head
    %meta{charset: 'UTF-8'}
    %title= current_page.data.title || "Middleman"
  %body
    .wrapper
      .contents
        = yield
         
      %aside.sidebar
        %p hoge
        %p fuga
        %p foo
     
    %footer.global-foter
      %small Soushi Yamamoto
```

- 先ず、共通部分のみで構成された `layout_base.haml`を作成します。

```haml
!!!
%html
  %head
    %meta{charset: 'UTF-8'}
    %title= current_page.data.title || "Middleman"
  %body
 
    = yield
         
    %footer.global-footer
      %small Soushi Yamamoto
```

- 次に、`layout_a.haml` と `layout_b.haml` で残りの部分(異なる部分)を記述します。
- `wrap_layout` という関数を呼び出し、引数に使用するレイアウトを指定します。指定する際はファイル名をそのまま記述するのではなく、上の例にあるように**:を冒頭につけてレイアウト名を記述します**。これは**シンボルというRubyの記法の一つ** *1です。呼び出し元はlayout_base.hamlの= yieldの部分に来ます。この機能はオブジェクト指向の継承がイメージとして近いかもしれません。[*1 Rubyのシンボルについてはこちら(すぐに忘れる脳みそのためのメモ)](http://jutememo.blogspot.jp/2008/01/ruby.html)

- `layout_a.haml`

```haml
- wrap_layout :layout_base do
  %header.global-header
    %h1 Page title
    
  .contents
    = yield
```

- `layout_b.haml`

```haml
- wrap_layout :layout_base do
  .wrapper
    .contents
      = yield
         
    %aside.sidebar
      %p hoge
      %p fuga
      %p foo
```

---

注意：**ここから先(7章「パーシャル」)はバグあり。未検証なので、今後検証すること。**


---

#7 パーシャル

- 外部ファイルをインクルードする機能と基本的には同じです。グローバルヘッダーやグローバルフッター、グローバルナビなど複数ページにわたって共通で使用されるようなコンポーネントは**外部ファイル化しておくことでコードの重複を避ける**ことができます。 先の例を続けます。 `layout_a.haml` にはグローバルヘッダー要素がありますが、これをパーシャル化して `layout_b.haml` やそれ以外のファイルでも使用できるようにします。**パーシャルのファイル名は先頭に_を付けます。** 共通するレイアウトの一部ということで、**layouts/libというディレクトリを新規に作成してそこに配置**します。

- `layouts/lib/_global_header.haml`

```haml
%header.global-header
  %h1 Page title
```

- 次にpartialメソッドを使って `layout_a.haml` にグローバルヘッダー要素を配置します。
- partial という関数の引数として配置したいパーシャルファイルのパスを指定します。ポイントとしてはファイル名にはある **先頭の_と拡張子は記述しない** ということです。layout_b.haml にグローバルヘッダーを配置したい場合も上記と同様の手法で実現することができます。

- `layout_a.haml`

```haml
- wrap_layout :layout_base do
  = partial 'layouts/lib/global_header'

  .contents
    = yield
```

- パーシャルとして外出しできたのは良いのですが、見出しの文言が Page title と固定になっていては、使い勝手が良い機能とはいえません。**呼び出しの際に見出しの文言を引数として渡す**ことでこの問題を解決することができます。パーシャルファイルを以下のように修正します。

- `layouts/lib/_global_header.haml`

```haml
%header.global-header
  %h1= title
```

- titleという変数に書き換えました。この変数に対してパーシャル呼び出し時に値を引数として渡します。`layout_a.haml` を以下のように修正します。
- localsというオブジェクトの中にパラメータを指定して値を渡しています。jQuery プラグインにオプションを渡すようなものだと考えておけば問題ないでしょう。

- `layout_a.haml`

```haml
- wrap_layout :layout_base do
  = partial 'layouts/lib/global_header', locals: {title: "My Title A"}

  .contents
    = yield
```