2017年10月27日金曜日

Sinatra で haml を使ってみた (partial も試してみる)

概要

Sinatra のテンプレートエンジンはデフォルトで erb が使えます
haml を使うこともできるので使ってみました
また、helper メソッドを定義することで別のテンプレートを参照する方法も紹介します

環境

  • CentOS 7.3
  • Ruby 2.3.3p222
  • sinatra 2.0.0
  • haml 5.0.4

各種ライブラリのインストール

  • bundle init
  • vim Gemfile
gem "sinatra"
gem "haml"
  • bundle install --path vendor

app.rb の作成

まずはアプリ本体を作成します

  • vim app.rb
require 'sinatra'
require 'haml'

set :bind, '0.0.0.0'

get '/' do
  @msg = "hello"
  haml :index
end

erb 同様インスタンス変数を定義することで haml テンプレート内でその変数を参照することができます

haml テンプレートの作成

とりあえず簡単な HTML を出力する haml テンプレートを作成します

  • vim views/index.haml
!!!
%html
%head
  %title haml test
%body
%h1 #{@msg}
%p ほげ

haml ではタグ情報を % を付与するだけで表現できます
見やすいように好きなようにインデントして OK です
文字列も特にダブルクォートで囲まなくて OK です、逆に囲んでしまうと表示されてしまうので注意です
先頭のビックリマーク 3 は「haml front matter」と呼ばれる特殊な命令でメタデータなどを設定することができます
#{@msg} とすることで app.rb 内で定義した変数を参照することができます

とりあえず動作確認

これでまずは動作確認してみましょう

  • bundle exec ruby app.rb

localhost:4567 にアクセスすると簡単な HTML が表示されると思います

css を追加してみる

class 属性を追加して css で装飾してみましょう

  • vim view/index.haml
!!!
%html
%head
  %title haml test
  %link{href: "style.css", rel: "stylesheet", type: "text/css"}
%body
%h1 #{@msg}
%p{class: "p1"} ほげ

%p に class 属性を追加しました
他にも追加するための記述はありますが個人的にはこれが好きです
そして %head 内にスタイルシートの参照を追記しています

スタイルシートを追加する

これは既存のスタイルを追加するだけです
haml 内でスタイルシートを定義することもできますが今回は別ファイルにしました

  • vim public/style.css
.p1 {
  font-size: 48px;
}

これで動作確認してみると文字が大きくなりスタイルが適用されているのがわかると思います
余談ですが Sinatra の場合画像やスタイル、JavaScript などの公開ファイルは public 配下に配置します

別の haml ファイルを作成して参照してみる

テンプレートファイルは共通する部分を切り出して部分的に管理したくなります
rails だと render という機能がありデフォルトで使用できるのですが、Sinatra ではそのような機能はありません
なので、今回は helper として partial というメソッドを定義して haml テンプレート内から別の haml テンプレートを参照してみたいと思います

ヘルパーモジュールの追加

  • vim helpers/sinatra_partials.rb
module Sinatra::Partials
  def partial(template, *args)
    template_array = template.to_s.split('/')
    template = template_array[0..-2].join('/') + "/_#{template_array[-1]}"
    options = args.last.is_a?(Hash) ? args.pop : {}
    options.merge!(:layout => false)
    locals = options[:locals] || {}
    if collection = options.delete(:collection) then
      collection.inject([]) do |buffer, member|
        buffer << haml(:"#{template}", options.merge(:layout =>
        false, :locals => {template_array[-1].to_sym => member}.merge(locals)))
      end.join("\n")
    else
      haml(:"#{template}", options)
    end
  end
end

何をしているかというと引数で与えられた template ファイルにアンダースコアを追加して haml 関数をコールしています
アンダースコアを追加しているのは非参照のファイルであることを明示的にするためです
またテンプレート内に与える引数をオプションで指定することができます

アプリでヘルパーモジュールを参照する

追加したヘルパーモジュールを app.rb から呼び出します

  • vim app.rb
require 'sinatra'
require 'haml'
require './helpers/sinatra_partials.rb'

set :bind, '0.0.0.0'
helpers Sinatra::Partials

get '/' do
  @msg = "hello"
  haml :index
end

これで haml テンプレート内で partial メソッドが使えるようになります

haml テンプレートの変更

別の haml テンプレートを呼び出してみます

  • vim views/index.haml
!!!
%html
%head
  %title haml test
  %link{href: "style.css", rel: "stylesheet", type: "text/css"}
%body
%h1 #{@msg}
%p{class: "p1"} ほげ
= partial "footer", :locals => {:key => "footer!"}

最後の 1 行を追加してます
haml 内で関数をコールする場合は = を使います
そしてヘルパーモジュール内で定義した partial メソッドをコールします
今回は _footer.haml というテンプレートを呼び出します
またオプションで :locals を追加することで _footer.haml 内で変数の値を参照できるようにします

_footer.haml の作成

参照される側の haml ファイルを作成します

  • vim views/_footer.haml
%h2 #{key}

先程も少し紹介しましたが非参照がわかるようにアンダースコアを付与するのを忘れないようにしてください
内容は渡された変数の内容を表示しているだけです

動作確認

これで動作確認すると別の haml ファイルの内容も HTML に反映されていると思います
またローカル変数の値も参照できていると思います

最後に

Sinatra + haml を使って HTML を表示してみました
erb よりも haml を使ったほうが記述量が減らせるのが嬉しい点かなと思います
また今回紹介した partial は erb でも使うことができます
haml とコールしてる部分を erb に変更するだけです

参考サイト

0 件のコメント:

コメントを投稿