IT・技術研修ならCTC教育サービス

サイト内検索 企業情報 サイトマップ

研修コース検索

コラム

Ruby & Rails

CTC 教育サービス

 [IT研修]注目キーワード   Python  UiPath(RPA)  最新技術動向  OpenStack  システムトラブルシュート 

第26回 altERBで楽々Railsコーディング! ~Hamlの紹介~ (藺藤卓実) 2016年7月

こんにちは。 藺藤です。

今回のRuby & Railsコラムでは「altERBで楽々Railsコーディング」と題し、Railsでも利用できるGemの一つ、「Haml」を紹介します。(*1) Hamlは簡潔な記述でHTMLを作成できるテンプレートエンジンです。

Hamlとは

Hamlの説明に入る前に、RailsでビューのHTMLを作成するときにデフォルトで利用するERBを見てみましょう。(*2)

ERBはRuby製テンプレートエンジンです。 HTMLに限らず、様々なテキストファイル中にRubyコードを埋め込みたいときに利用されます。 ERBファイルの拡張子は.erbです。 例えば、挨拶するHTMLを作成する場合には次のように書きます。(*3)

[greeting.html.erb]
<div id="message"><%= "こんにちは。" %></div>
[greeting.html]
<div id="message">こんにちは。</div>

この例を応用させて、現在時刻に応じて「おはようございます」「こんばんは」等と挨拶させることもできます。

ERBを利用することで、Webページにアクセスした時点でのデータベースの値や、ユーザの入力に基づいた計算結果などを含む、いわゆる動的なページを作成することができます。 ERB自体はプログラマにとって馴染み易く、取り組みやすいものです。 類似の技術としてPHP言語や、Java言語のJSPが挙げられます。

ERBは便利なものですが、汎用的なテンプレートエンジンであるため、HTMLを書き下すことを目的とする場合には冗長な記述になりがちです。 このような場合、専用のテンプレートエンジンを利用することでHTMLを「より簡潔に記述し」、「より素早くコーディングできる」ようになります。

今回はRailsのERBを代替できるテンプレートエンジン(="altERB")として「Haml」を紹介します。 Hamlを使うと、上で示した挨拶の例は次のように書き下せます。 なお、Hamlの拡張子は.hamlです。

[greeting.html.haml]
#message こんにちは。
[greeting.html]
<div id="message">こんにちは。</div>

Hamlの詳しい書き方はこの後で紹介しますが、ここでは「erbと比べてソースコードが非常に短くなった」ことに注目してください。 実際に文字数を数えてみると

  • greeting.html.erb ... 39文字
  • greeting.html.haml ... 15文字

と、長さは実に半分以下になりました。(ここでは半角・全角文字、スペースいずれも1文字と数えています。)

Hamlでは、閉じタグを書く必要がありません。 また、利用頻度の高い、idやclassの指定に関してはCSSと同様に「#」や「.」で指定することができます。 このようなHamlの記述ルールによって、プログラマは非常にすっきりとコーディングすることができます。

Hamlの導入>

Hamlを導入するためには、端末を開いて以下のコマンドを実行してください。

$ gem install haml

無事にインストールされたでしょうか。 動作確認しましょう。

初めに、新しいファイルgreeting.html.hamlを作成します。 内容は上の例と同じものにしてください。 HamlをHTMLにコンパイルするには、hamlコマンドを実行します。

[greeting.html.haml]
#message こんにちは。
$ haml greeting.html.haml
#=> <div id="message">こんにちは。</div>

このように、コンパイル結果のHTMLが表示されていれば成功です。 変換結果をファイルに書き出したい場合には、hamlコマンドに「入力ファイル」「出力ファイル」の順で指定してください。

$ haml greeting.html.haml greeting.html

作成されたHTMLファイルgreeting.htmlをブラウザで確認してください。

Hamlコマンドで利用できるオプションを調べたい場合、「-h」オプションが利用できます。

$ haml -h

「-v」オプションを利用し、インストール済みのHamlのバージョンを確認しておきます。

$ haml -v
#=> Haml 4.0.7

筆者が利用しているのは、Haml バージョン4.0.7のようです。 

今回のコラムは、以下に記すような筆者の手元の環境で動作確認しています。

  • CentOS 6.7
  • Ruby 2.2.4
  • Haml 4.0.7
Hamlの文法>

さて、ここまでは文法を一切説明しないまま、とりあえずHamlを使ってきました。 ここからは文法を説明します。 ぜひ、実際に入力・出力をしながら読み進めてください。(コマンドの実行は省略します。)

タグの記述「%tag content」

HTMLタグを記述するためには「%」記号を利用し、タグの名前を指定します。 また、タグの名前の後ろに半角スペースを1文字入れると、続く部分はタグの内容として解釈されます。

%h3 タグの記述「%tag content」
%p これはpタグです

#=> <h3>タグの記述「%tag cotent」</h3>
#=> <p>これはpタグです</p>
属性の指定「{attr1: value1, attr2: value2, ... }」

%tagに続けてRubyのHash形式で属性を指定できます。 例として、idを指定する場合は次のように書けます。

%p{id: "explanation-attr"} 属性の指定「{attr1: value1, attr2: value2, ... }」
#=> <p id="explanation-attr">属性の指定「{attr1: value1, attr2: value2, ... }」

この形式を利用することでhrefやaltなど、任意の属性を指定できます。

id、classの指定「#」「.」

idやclassの指定は利用頻度が高いと考えられることから、Hamlではこれらの指定に関して特別な記法を認めています。 idの指定には「#」記号、また、classの指定には「.」記号を利用します。 "特別な記法"と言っても、CSSでお馴染みの記法ですね。

%div#my-id.my_class id、classの指定「#」「.」
#=> <div class="my_class" id="my-id">id、classの指定「#」「.」</div>

また、divタグは頻繁に利用するため省略形が認められています。 上のHamlコードは次のように書き換えることができます。

#my-id.my_class id、classの指定「#」「.」

#=> <div class="my_class" id="my-id">id、classの指定「#」「.」</div>

先頭に「%」記号が存在せず、idやclassの指定(「#」や「.」)がある場合には、%divを省略したものとして扱われます。

要素の入れ子

複数のタグの入れ子構造を作りたい場合、Hamlではインデントによって入れ子の親・子を表現します。 また、インデントの深さが元に戻った場合にはタグの終了を意味します。

実際にコードを見てみましょう。

#parent
  親
  #child
    子
    #grandchild 孫

#=> <div id="parent">
#=>   親
#=>   <div id="child">
#=>     子
#=>     <div id="grandchild">孫</div>
#=>   </div>
#=> </div>

インデントの深さは何文字でもよいですが、ここではRubyで標準的な2文字分のインデントを採用しました。

要素の入れ子に関しては、ついやってしまいがちな注意点がありますので、ここで指摘しておきます。

(1) 子を持つタグに対し、「タグの内容」を書くことはできない

次のような書き方はできません。 「Illegal nesting(不正なネスト)」エラーが発生します。

#parent
  #child
    #grandchild 孫

#=> Illegal nesting: content can"t be both given on the same line as %div and nested within it.

#parent は子要素#childを持つにもかかわらず、#parentに続いてタグの内容("親"というテキスト)を記述してしまっています。

HTMLで考えると#parentは複数の子要素("親"というテキストと、idがchildのdivタグ)を持っています。 Hamlでは、これらは対等に扱わないといけません。 先に示したように、インデントを一つ下げて、同じレベルに全ての子要素を併記します。

(2) テキストに対して、子要素を持たせることはできない

急いでコーディングしていると、うっかり次のようなコードを書いてしまうかもしれません。 このときにも「Illegal nesting」エラーが発生します。

#parent 
親
  #child
  
    #grandchild 孫

#=> Illegal nesting: nesting within plain text is illegal.

この場合、インデントが適切でないため、「テキスト"子"に対して子要素#grandchildを追加する」ものと解釈されてしまいます。 これは、HTMLで考えてみると当たり前ですが、不適切な構文です。

Rubyコード

Hamlで、Rubyコードを実行する2つの構文を紹介します。

(1) コードを実行する「-」

半角のハイフンから始まる行は「Rubyコードが実行される」ものとして扱われます。 この部分には文法的に正しいRubyコードを記述する必要があります。

初めに、繰り返し処理の例を見てみましょう。

- 3.times do |i|
  こんにちは
#=> こんにちは
#=> こんにちは
#=> こんにちは

Integer#timesメソッドを利用して、「こんにちは」を3回表示させました。 

Rubyコードを実行させるときのポイントは

  • Rubyコードを書く行を「-(ハイフン)」で始めること
  • Rubyのブロック相当部分をインデントすること
  • end は不要であること(インデントを利用してブロックの範囲を決めているため)

の3つです。 インデントや、endは不要であることを忘れないようにしてください。

条件分岐構文も同様です。 別の例を見てみます。

- r = rand(2)
- if r.odd?
  おはようございます
- else
  おやすみなさい
#=> おやすみなさい    # ※結果はランダムです。

この例は乱数を利用しているため結果はランダムですが、条件分岐により「おはようございます」または「おやすみなさい」のどちからが表示されます。

(2) 値を出力する「=」

半角の「=(イコール)」を利用して、Rubyコードの評価値を出力できます。 これはERBに似ていて、直感的な記法ではないでしょうか。

- 3.times do |i|
  = "#{i}回目の評価値"

#=> 0回目の評価値
#=> 1回目の評価値
#=> 2回目の評価値

「-」や「=」の右辺はRubyとして正しい文法である必要があるため、出力文字列を""(クォーテーション)で囲っています。 この例では3回繰り返し、何回目の繰り返しであるのかを表示させています。

コメント

これはHamlの構文というよりもRubyの構文そのものですが、コメントも利用できます。

例を示します。

- # ここにコメント可能
- 3.times do |i|  # ここにもコメントできる
  = "#{i}回目の評価値"  # こんなところにもコメントできる

当然ながら、これらはただのコメントですので実行結果は変わりません。 Rubyコード部分のコメントは、HTMLコメントとは異なり、実行結果のHTMLには含まれません。

文法に関しては以上です。  ここまで紹介したものだけでも、HTMLの作成をかなり省力化できます。 ぜひお試しください。

Hamlの応用的な利用方法に関しては、本家リファレンス(英語)が参考になります。(*4)基本文法をマスターしたのち、リファレンスの方もご覧ください。

Railsでの利用

最後に、RailsでHamlを利用する方法について述べます。

Hamlの導入にあたっての注意ですが、1つのRailsアプリケーション上で、ERBファイルとHamlファイルを共存させることができます。 これはファイルの拡張子(.erbか、.hamlか)に従ってRailsが判断し、適切にコンパイルしているためです。

このため、アプリケーション開発の途中からHamlを導入した場合でも、既存のerbファイルを全て書き換える必要はありません。 まずは小さく始めることができます。 もちろん、望むならばすべてのERBファイルをHamlで書き換えることも可能です。(この場合は拡張子を手動で変更してください。)

RailsでHamlを利用できるようにするために、'haml-rails'を利用します。(*5) まず、Gemfileに以下を追加します。

[Gemfile]
gem 'haml-rails'

いつも通り、bundle installを実行してください。

$ bundle install
#=> Installing haml 4.0.7
#=> Installing haml-rails 0.9.0

Hamlが無事にインストールされました。(実行結果は一部抜粋しています。)

それでは適当にScaffoldしてみましょう。 コントローラやモデルはいつもの通りですが、ビューのファイルが「.html.erb」ではなく「.html.haml」で作成されています。

$ rails g scaffold test
#=> invoke haml
#=> create   app/views/tests
#=> create   app/views/tests/index.html.haml 
#=> create   app/views/tests/edit.html.haml 
#=> create   app/views/tests/show.html.haml 
#=>     ...

Scaffoldができたら、いずれかのHamlファイルをエディタで開いてみてください。 Railsジェネレータで作成されたファイルも、Hamlの文法を使ったものに改められていることを確認できます。

あとは先ほど説明したHamlの文法を使ってHamlファイルを編集してゆきます。

参考までに、Scaffold機能を使って「test」リソースをERB、Hamlそれぞれの場合で作成してみました。 2つの場合でindexビューの行数、文字数をカウントしてみると、

  • app/views/tests/index.html.erb ... 24行(455文字)
  • app/views/tests/index.html.haml ... 20行(346文字)

とhamlの方が2割ほど圧縮されています。 

動的な部分(Rubyコード)が増えると、Hamlによる圧縮率は下がってしまいます。 一方、レイアウトのためのdivタグ等、静的な部分が増えると、より一層Hamlによる圧縮の恩恵が大きなものになります。

こちらのブログ(*6)では、「Scaffoldによって作成されたERBファイルをSlimに書き換える」といったことをしています。 この記事も参考になるのではないでしょうか。

まとめ

今回は「altERBで楽々Railsコーディング」と題し、HTMLテンプレートエンジン「Haml」を紹介しました。 

Hamlを利用すると簡潔な記述でHTMLを作成できるため、ソースコードがどんどん複雑化してゆく事態を軽減できます。 行数・文字数共に大きさを抑えられるため、ソースコードが全体的に短く、見やすいものになります。

行数・文字数を圧縮できることも魅力的ですが、筆者としては、

  • 何重もの入れ子構造がきれいにインデントされること(=そうせざるを得ないこと)
  • 閉じタグを気にしなくて良いこと(=無数にある</div>を気にしなくて良い)

の2点が便利だと感じます。 ここには全文を示しませんが、RailsのScaffold機能を利用して

  • index.html.erb
  • index.html.haml

の2つを作成し、実際に比較してみてほしいと思います。 きっと、筆者の感じた2つの魅力を実感していただけるものと思います。 ぜひ、Hamlを活用してみてください。

さて、少しだけ次回の宣伝ですが、次回はHaml同様にRailsコーディングを楽にしてくれるテンプレートエンジン「Slim」をご紹介したいと思います。 次回のコラムもお楽しみに。

それでは、Enjoy Ruby!

注釈

*1 : 「Haml」の本家サイト。(英語) チュートリアルやリファレンスもありますので、ぜひ一読ください。
http://haml.info/

*2 : ERBについてはこちらの記事を参照のこと。
http://magazine.rubyist.net/?0017-BundledLibraries

*3 : ERBはコマンドラインからも実行できます。 次のコマンドを実行すると、コンパイルされた結果を表示できます。
$ erb greeting.html.erb

*4 : 「Haml」のリファレンス。(英語) Hamlがかなり詳細に説明されています。
http://haml.info/docs/yardoc/file.REFERENCE.html

*5 : 「Haml-rails」のGitHubページ。(英語) 既存のERBファイルをHamlに変換する方法も記されているなど有益です。
https://github.com/indirect/haml-rails

*6 : 参考にさせていただきました。
http://ruby-rails.hatenadiary.com/entry/20141001/1412097051

*7 : 本コラム執筆にあたり、参考にさせていただきました。
「Hamlの書き方」:
http://qiita.com/watak676/items/525ad3d8a1297e3244e3

「Hamlが5分で分るチートシート[Rails初心者チュートリアル]」
http://morizyun.github.io/blog/beginner-rails-tutorial-haml/

 


 

 [IT研修]注目キーワード   Python  UiPath(RPA)  最新技術動向  OpenStack  システムトラブルシュート