初めての Middleman シリーズ初めてのMiddleman:データファイルとデータファイルを使った動的ページ生成
前回の記事初めてのMiddleman:Sass MixinライブラリのBourbon, Neatを導入してみるでSassのMixinライブラリであるBourbon / Neatのインストールからコンパイルまで勉強しました。今回は新たにデータファイルについて理解し、動的にページを生成してみたいと思います。
データファイルを作る
わかりやすい例を挙げると、ナビゲーションの各リンクに含まれるタイトルやURLをデータファイルで管理することでデータとビューを切り離すことができます。このデータファイルはYAMLやJSON形式で作ることができ、簡単にテンプレートから呼び出せます。詳しくは公式ドキュメントのデータファイルもチェックしてみてください。
ナビゲーションをまとめたデータファイルを作る
データファイルのわかりやすい例として、ナビゲーションのデータファイルを作りレイアウトに組み込んでみます。
nav.yml
ナビゲーションのデータファイルはdata/nav.yml
で保存します。
-
slug: 'home'
name:
ja: 'ホーム'
en: 'home'
path: ''
-
slug: 'blog'
name:
ja: 'ブログ'
en: 'blog'
path: 'blog/'
-
slug: 'about'
name:
ja: 'このサイトについて'
en: 'about'
path: 'about'
レイアウトにナビゲーションを追加
レイアウトファイルにナビゲーションに関する指定を追加します。ナビゲーションデータから項目を取り出すにはeachメソッドを使います。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title><%= current_page.data.title || "The Middleman" %></title>
<%= stylesheet_link_tag "common" %>
</head>
<body>
<%= partial('modules/header', :locals => { :description => 'hogehoge' }) %>
<ul id="nav">
<% data.nav.each do |item| %>
<li><%= link_to item.name.ja, item.path %></li>
<% end %>
</ul>
<%= yield %>
</body>
</html>
ビルド
ビルドしてみます。
$ middleman build
identical build/assets/css/common.css
update build/index.html
ビルドされたHTMLに下記のようなナビゲーションリストが追加されていれば成功です。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Hello World</title>
<link href="/assets/css/common-d7f822e6.css" rel="stylesheet" type="text/css" />
</head>
<body>
<header>
<h1>example.com</h1>
<p>hogehoge</p>
</header>
<ul>
<li><a href="/">ホーム</a></li>
<li><a href="blog/">ブログ</a></li>
<li><a href="about.html">このサイトについて</a></li>
</ul>
<p>Hello World</p>
</body>
</html>
これは一例ですが、データファイルは様々な使い方ができる便利な機能です。
データファイルをもとに動的にページを生成する
スピーカーの情報をデータファイルにまとめ、スピーカー1人1人に独立したHTMLページを生成する例を紹介します。動的ページをつくるにはProxyという機能を使います。Proxyに対してテンプレートやデータを渡してページを生成します。
必要なファイル
動的ページを別のデザインにしたりデータファイルの値を渡して思い通りのページを実現しようとすると下記のようなファイルが必要になります。
- データファイル:ページ毎のデータを定義する
- テンプレート:生成するファイルのベースとなるファイル(レイアウトファイルを呼ぶ)
- レイアウト:タイトルタグやパーシャルに独自の値を渡したい場合に専用のレイアウトが必要
データファイル
下記のようにデータファイルにはスピーカーの情報を配列で定義します。
data/speakers.yml
この3人のスピーカー毎にページを生成します。
-
slug: 'yamada-tarou'
name: '山田 太郎'
company: '山田株式会社'
position: '猫'
profile: '吾輩わがはいは猫である。名前はまだ無い。どこで生れたかとんと見当けんとうがつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。'
link: 'http://whiskers.nukos.kitchen/'
-
slug: 'satou-jirou'
name: '佐藤 次郎'
company: '佐藤株式会社'
position: '犬'
profile: '吾輩わがはいは犬である。名前はまだ無い。どこで生れたかとんと見当けんとうがつかぬ。何でも薄暗いじめじめした所でワンワン泣いていた事だけは記憶している。'
link: 'http://whiskers.nukos.kitchen/'
-
slug: 'suzuki-saburo'
name: '鈴木 三郎'
company: '鈴木株式会社'
position: 'ウサギ'
profile: '吾輩わがはいは兎である。名前はまだ無い。どこで生れたかとんと見当けんとうがつかぬ。何でも薄暗いじめじめした所で静かに泣いていた事だけは記憶している。'
link: 'http://whiskers.nukos.kitchen/'
専用のレイアウト
既存のlayout.erb
をそのまま使えれば余計な手間が省けるのだけれど、残念ながらできません。なぜかというと以下のcurrent_page.data.title
にProxyからはデータを渡せないんですね(わかってないだけで方法はあるかもしれない)。今回は別のレイアウトを作って出力ヘルパーを使います。出力ヘルパーとはコンテンツ側からテンプレートやレイアウトにデータを投げることができる便利なヘルパーです。詳しくは公式ドキュメントの出力ヘルパーを確認してください。
layouts/speaker.erb
スピーカー用のレイアウトを下記のように作ります。タイトルタグは出力ヘルパーのyield_content(...)
を使って投げられたデータを出力します。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title><%= yield_content(:title) %></title>
<%= stylesheet_link_tag "common" %>
</head>
<body>
<ul>
<% data.speakers.each do |speaker| %>
<li><%= link_to speaker.name, '/speakers/' + speaker.slug + '.html' %></li>
<% end %>
</ul>
<%= yield %>
</body>
</html>
テンプレート
レイアウトの次に、Proxyを実行する際に指定するテンプレートを作ります。
templates/speaker.html.erb
テンプレートではYaml FrontMatterを使ってレイアウトファイルspeaker
を指定します。また、出力ヘルパーの投げる側でcontent_for(...)
を使います。第一引数の:title
が識別子ですね。speaker.name
でスピーカー名を渡しています。
---
layout: speaker
---
<% content_for(:title, speaker.name) %>
<h1><%= speaker.name %></h1>
<p><%= speaker.profile %></p>
これで必要なファイルの準備ができました。
config.rbにProxyを定義する
最後にconfig.rb
にProxyを定義します。ただの設定ファイルかと思いきやconfig.rb
の中でも簡単にデータにアクセスできます。データをeachメソッドを使ってレコードを取り出し、speaker
に入れて各所で呼び出します。:locals
というのはテンプレートで利用できる変数です。また、:ignore => true
を使ってテンプレートファイル/templates/speaker.html.erb
自身がコンパイルされないようにします。
# create speaker pages
data.speakers.each do |speaker|
proxy "/speakers/#{speaker.slug}.html", "/templates/speaker.html",
:locals => { :speaker => speaker },
:ignore => true
end
これですべての準備ができました。
ビルド
それではビルドしてみましょう。
$ middleman build
identical build/assets/css/common.css
create build/speakers/yamada-tarou.html
identical build/index.html
create build/speakers/satou-jirou.html
create build/speakers/suzuki-saburo.html
speakers
ディレクトリの中に各スピーカーのslugがファイル名になったHTMLが作られました。 HTMLの中身もタイトルがそれぞれのスピーカー名になり、スピーカー全員のリンクもできています。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>佐藤 次郎</title>
<link href="/assets/css/common-d7f822e6.css" rel="stylesheet" type="text/css" />
</head>
<body>
<ul>
<li><a href="/speakers/yamada-tarou.html">山田 太郎</a></li>
<li><a href="/speakers/satou-jirou.html">佐藤 次郎</a></li>
<li><a href="/speakers/suzuki-saburo.html">鈴木 三郎</a></li>
</ul>
<h1>佐藤 次郎</h1>
<p>吾輩わがはいは犬である。名前はまだ無い。どこで生れたかとんと見当けんとうがつかぬ。何でも薄暗いじめじめした所でワンワン泣いていた事だけは記憶している。</p>
</body>
</html>
これで、データファイルに必要な情報を追記するだけで簡単にページが作れるようになりました。データさえ用意すれば良いのでコンテンツ追加が捗りますね。更新がとても楽になります。
今回はここまで。
次回はブログ機能について勉強したいと思います。
次回:初めてのMiddleman:サイトにブログ機能を追加する
シリーズ
- 初めてのMiddleman:rbenv, bundler 環境でMiddlemanを使ったHello World
- 初めてのMiddleman:レイアウト機能でレイアウトとコンテンツを分離する
- 初めてのMiddleman:パーシャルを使ったコンテンツのモジュール化
- 初めてのMiddleman:SCSSのコンパイルとテンプレートの基礎
- 初めてのMiddleman:Sass MixinライブラリのBourbon, Neatを導入してみる
- 初めてのMiddleman:データファイルとデータファイルを使った動的ページ生成
- 初めてのMiddleman:サイトにブログ機能を追加する
- 初めてのMiddleman:Amazon S3にビルドされたファイルを同期する
- 初めてのMiddleman:HTML/CSS/JS/画像をビルド時に圧縮する
- 初めてのMiddleman:設定について
- 初めてのMiddleman:静的サイトのキャッシュとasset_hash拡張を使ったキャッシュのパージ
- 初めてのMiddleman:Middleman::S3Syncで使うAWS IAMユーザーのアクセスキー管理方法について
- 初めてのMiddleman:Helperを使ってGravatarのアイコンを表示する
- 初めてのMiddleman:アセットパイプラインを使った外部アセットファイルの読み込みと結合
- 初めてのMiddleman:Bowerを使ってjQueryなどのライブラリをロードする
- 初めてのMiddleman:スケルトンを自作する方法
- 初めてのMiddleman:Middleman Blogの記事データを使いやすく管理する方法
- 初めてのMiddleman:Middleman-blogのシングルブログを前提としたSkeletonを作った
- 初めてのMiddleman:Middleman-blogでマルチブログを試してSkeletonを作った
- 初めてのMiddleman:Markdown EngineをkramdownからRedcarpetに切り替える
- 初めてのMiddleman:RedcarpetとMiddleman::Rougeを使ったシンタックスハイライト
- 初めてのMiddleman:Middleman-Syntaxを使ったシンタックスハイライト
- 初めてのMiddleman:Middleman-Blogで記事毎に画像を管理する方法
- 初めてのMiddleman:Gulpを使ってサムネイル画像を生成する
- 初めてのMiddleman:Middleman-OGPのOGP画像指定を相対パスで設定する
- 初めてのMiddleman:Middleman-OGPでMiddleman-BLogにOGPを設定する
- 初めてのMiddleman:Middleman-Titleでタイトルタグを手軽に設定する
- 初めてのMiddleman:多言語化 - 言語ファイルの作成とヘルパーの埋め込み
- 初めてのMiddleman:Middleman-blogにカテゴリやシリーズなどのカスタムコレクションを追加する方法
- 初めてのMiddleman:Bowerで管理されているフォントファイルをインポートする