Posted at

Mojoliciousのテンプレートでレイアウトを自在に操る

More than 5 years have passed since last update.

テンプレートのレイアウトの話 。例えば…


  • デフォルトは2カラムで右側にサイドバー

  • でも about ページとかは1カラムにしたい

っていう要望よくあると思うんですよ。でMojoliciousの Mojolicious::Plugin::DefaultHelpers の中からヘルパーメソッドをいくつかチョイスして使えば実現可能です。ただ、ついつい分かりやすい layoutinclude メソッドだけを使ってこねくり回す感じでいわば強引に上記の1カラムと2カラムの切り替えを僕は以前やっていました。すると include するためのパーツをいくつも切り分けなくてはいけなくてちょっと管理が煩雑になるので最近使ってる手法を紹介します。

content メソッドと extends メソッドを使います。アプリの本体はMojolicious::Liteでこのように短く書いてみます。

#!/usr/bin/env perl

use Mojolicious::Lite;

get '/' => sub { shift->render('index') };
get '/about' => sub { shift->render('about') };

app->start;

/ にアクセスされたらデフォルトの2カラム、/about にアクセスが来たら1カラムで表示してみましょう。

まず、2カラムでも1カラムでも共通で使う 外枠 のラッパーを定義します。

@@ layouts/wrapper.html.ep

<!DOCTYPE html>
<html>
<head><title>Hello Mojolicious</title></head>
<body>
% content container => begin
<%= content %>
% end
%= content 'container'
</body>
</html>

content メソッドの中で一度「container」という名前でこれからつくる /layouts/default/layout/one_column の内容を読み込ませてすぐさま表示しています。次にデフォルトの2カラム、そして1カラムのテンプレートを書きます。

@@ layouts/default.html.ep

% extends 'layouts/wrapper';
% content container => begin
<div><%= content %></div>
<div id="sidebar">sidebar</div>
% end
%= content 'container'

@@ layouts/one_column.html.ep
% extends 'layouts/wrapper';
% content container => begin
<div><%= content %></div>
% end
%= content 'container'

extends メソッドで例の layouts/wrapper を呼び出して「container」という名前でテンプレートの実態を渡しています。これで


  • 一番外側がlayouts/wrapper

  • 中身はそれぞれlayouts/default, layouts/one_columnで実装

することが叶えられるのです。最後に、個別のテンプレート、つまりコントローラから呼び出されるモノについて書きましょう。ここは特に意識することなく layout メソッドで default もしくは one_column を指定するだけです!

@@ index.html.ep

% layout 'default';
2 cloumns!!

@@ about.html.ep
% layout 'one_column';
1 cloumn!!

ちょいラッパーとその中身をつくる仕掛けが複雑ですが、一度定義してしまえば、個別のテンプレートは layout メソッドで切り替えるだけでよいのでこれはなかなか良いですね。他にテンプレートの応用の仕方がありましたら本Advent Calendarにて記事を書いてくれると嬉しいっす!