hamlの基本とよくあるエラー集

# ◆概要
Ruby on Rails学習者向けのhamlの解説です。
初学者の方は基本的なclassなどの書き方は勿論ですが、特に後半の「hamlのよくあるエラー集」を参考にしていただければと思います。

# ◆hamlって？

html.erbの派生版。
少し難易度は上がるもののコードの量が減りhtml.erbに比べて読みやすいコードになりやすい。
Railsで使用する際にはhaml-railsというgemが必要。

## ●これがhtml.erb
```
<div id="information">
  <% if controller.action_name == "index" %>
    ここはトップページです。
  <% else %>
    ここはトップページではありません。
  <% end %>
</div>

<div class="back-gray border-black" id="menu">
  <%= link_to "トップページへ", root_path %>
  <br>
  <%= link_to hoge_path do %>
    hogeページへ
  <% end %>
</div>
```

## ●これがhtml.haml

```
#information
  -if controller.action_name == "index"
    ここはトップページです。
  -else
    ここはトップページではありません。
#menu.back-gray.border-black
  = link_to "トップページへ", root_path
  %br
  = link_to hoge_path do
    hogeページへ
```

## ●hamlのメリット

- 閉じタグ（\</hoge>）や<% end %>を記述しなくて良いので記述量が減る。
- 閉じタグ忘れなどの些細なミスが減る。
- インデント（半角スペース）のルールが厳しいので、コードが汚くなりにくい。

## ●hamlのデメリット

- html.erbの頃では出なかったエラーが出るので最初はエラーが頻出する。

---

#### ●Q. hamlってエラー出やすくなるだけだしerbで良くない？

<h4>●A. 確かに最初は戸惑いますがこの記事の内容が頭に入っていればそうそう躓くことはなくなるので慣れましょう！</h4>

# ◆hamlの基本

## ●タグ、class、IDの指定の仕方

```html:htmlの場合
<p class="hoge fuga" id="foo">
  こんにちは
  <br>
  いいお天気ですね
</p>
```

```haml:hamlの場合
%p#foo.hoge.fuga
  こんにちは
  %br
  いいお天気ですね
```


- タグを指定する際は「%タグ名」と書く（省略するとdivタグになる）。
- classを指定する際は「.class名」と書く。複数のclassを設定する場合は.class名を繋げる。
- idを指定する際は「#id名」と書く。

### ●タグ、class、idの書き方一覧

||html.erbの場合|html.hamlの場合|
|---|---|---|
|タグ|\<p>\</p>|%p|
|タグ+class|\<p class="hoge fuga">\</p>|%p.hoge.fuga|
|タグ+id|\<p id="fuga">\</p>|%p#fuga|
|タグ+id+class|\<p id="fuga" class="foo bar">\</p>|%p#fuga.foo.bar|

## ●ネスト（入れ子）の仕方

htmlの場合は以下のようにネストしました。

```html:htmlの場合
<p>
  <span>
    ほげほげふがふが
  <span>
</p>
```

hamlの場合は以下のようにネストしたいものの行のインデントを下げます（半角スペースを入れます。）

```haml:hamlの場合
%p
  %span
    ほげほげふがふが
```

## ●viewファイル内でRubyのコードを使う。

viewファイル内でRubyの処理を使いたい場合、erbでは以下のように`<%= %>`や`<% %>`を使いました。

```html:erbの場合
<% fruits = ["りんご", "みかん", "ぶどう"] %>
<% fruits.each do |fruit| %>
  <%= fruit %>
<% end %>
```

hamlの場合は以下のように書くので`<% end %>`は不要です（書かないだけで存在はしています）。

```haml:hamlの場合
- fruits = ["りんご", "みかん", "ぶどう"]
- fruits.each do |fruit|
  = fruit
```

||html.erbの場合|html.hamlの場合|使い分け|
|---|---|---|---|
|画面に出力したくないもの|<% if user_signed_in? %>| - if user_signed_in? |if, eachなど|
|画面に表示したいもの|<%= current_user.name %>|= current_user.name|form_with, renderなど|


# ◆hamlのよくあるエラー集

hamlではerbと違って文法を間違えるとすぐにエラーが起きます。エラーは大抵の場合インデントに依るものです（もしくはカンマなど）。
主要なものを紹介します。

## ●パターン①：全体のインデントが統一されていない。

インデントの増やしていく数は、最初のインデントによって決まります。例えば最初にネストした際にインデントを２つ下げた場合、以降の行でも2つずつ下げる必要があります。途中で変更するとエラーが出ます。インデントは半角スペース2つずつで統一すると覚えておきましょう。

```haml:2行目はインデントが2つに対して、4行目、6行目はインデントが1つになっている
.hoge
  .fuga
.foo
 .bar
.abc
 .def
```

### ・実際のエラー画面

![haml_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421175/726b7049-8374-e749-dac0-a907b47f3b22.png)

## ●パターン②：途中で一気にインデントが増えている。

インデントは徐々に増やしていく必要があります。例えば最初にインデントを2つ下げた場合、以降も２つずつ下げましょう。途中で一気に3つ4つ増やすとエラーが起きます。

```haml:2行目はインデントが2つに対して、3行目で一気に4つ増えている。
.hoge
  .fuga
      .foo
```
### ・実際のエラー画面

![haml_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421175/553671fb-b261-27bc-8a18-305dfea3f285.png)

## ●パターン③：ネストしてはいけないものでネストしている、もしくはネストするべきものでネストしていない。

hamlでは`<% end %>`は記述しませんが省略しているだけで存在はしています。ネストを誤るとendの数がおかしくなります。
SyntaxErrorが出た際に以下のようなメッセージが含まれている場合はendの数がおかしくなっています。

```html:endが多い
syntax error, unexpected ensure, expecting end-of-input ensure
```

```html:endが足りない
syntax error, unexpected end-of-input, expecting end
```

それではパターンをいくつか見ていきましょう。

---
ネストしてはいけないものでネストするとエラーが発生します。

```haml:ネストしてはいけないものでネストしている①
= render 'foo'
  .hoge
```

```haml:ネストしてはいけないものでネストしている②
= form_for @message do |f|
  = f.text_field :text
    .hoge
```

### ・実際のエラー画面

![haml_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421175/29a3db9a-39da-863d-ed7c-e97c29f884ba.png)

---
ネストするべきものでネストしていない場合もエラーが発生します。doがある場合は何らかをネストする必要があります。

```haml:form_forはネストしなければならない
= form_for @message do |f|
= f.text_field :text
```

```haml:each~doはネストしなければならない
- fruits = ["りんご", "みかん", "ぶどう"]
- fruits.each do |fruit|
= fruit
```

```haml:link_to~doはネストしなければならない
= link_to root_path do
トップページへ
```

### ・実際のエラー画面

![haml_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421175/c0c66396-5d1d-e409-0ff9-2cb08c341c4a.png)

---

文字列で何かをネストした際にもエラーが発生します。

```haml:文字列でネストしてはいけない①
.hoge
  こんにちわ
    .fuga
      おはよう
```

```haml:文字列でネストしてはいけない②
.hoge  こんにちわ
  .fuga
    おはよう
```

### ・実際のエラー画面

![haml_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421175/cf904878-c3d7-e1ce-16ac-29d5a745d9a0.png)

「文字列でネストしてはいけない①と②」は書き方が違うだけで内容は同じです。②のような書き方（要素と同じ行に文字列を書く）はエラーを起こしやすいので避けましょう。

---

## ●パターン④：1行目にインデントがある。

1行目はインデント（半角スペース）なしである必要があります。

```haml:1行目にインデントがあります。
  .wrapper
    .header
      .header__title
        ページタイトル
```

### ・実際のエラー画面

![haml_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421175/32f94fe6-a709-4797-3d29-660d89215153.png)

---

## ●パターン⑤：カンマに過不足がある。

haml特有というよりはerbでも発生しますが紹介します。

```haml:「：text」の後ろにカンマ（,）が必要
= form_for @message do |f|
  = f.text_field :text placeholder: "ほげほげ"
```

### ・実際のエラー画面

![haml_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421175/7653874b-4c03-8d88-bc83-3e9236cd8097.png)