Slim は Ruby 製テンプレートシステム。インデント記法で HTML や XML を簡潔に記述できる。
この記事は,「Slim をなんとなく使っている」という人向けに,既存の Slim コードを見直してみようと呼びかけるもの。
Slim だってリファクタリング(結果を変えずに記述を合理化)すれば可読性や保守性が向上するはず。
無駄な do
- 3.times do
p わん
ブロックパラメーターが無いなら do
は省略できる。
- 3.times
p わん
属性値は文字列化してくれる
td colspan="2" foo
これは単に次のように書ける。
td colspan=2 foo
colspan=
の右には Ruby の式を書くことができて,式の評価結果は to_s
メソッドで文字列化されるため。
id 属性はナンバー記号で
p id="signature" Eugene
id
属性は便利な #
記法がある。
p#singnature Eugene
ただし,id が「:
」などを含んでいる場合はこの記法は使えないので
p id="foo:bar" Hoge
などと書くしかない。
一方,アンダースコアやハイフンは使っても大丈夫。
p#foo_bar-baz Hoge
追記:2020-05-23
2020 年 5 月 8 日にリリースされた slim 4.1.0 で,ナンバー記号表記の id に :
などが使えるようになった。つまり,このバージョン以降なら
p#foo:bar Hoge
で期待どおり
<p id="foo:bar">Hoge</p>
が得られる。
id だけでなくクラスも同様。
class 属性はピリオド記法でいくつでも
p class="foo bar" hoge
class
属性もピリオド記法で書ける。クラス名が複数ある場合はピリオド記法を重ねればよい。
p.foo.bar hoge
ナンバー記号との併用もできる。
p#foo.bar.baz hoge
クラス属性のピリオド記法と普通の記法は混在可能
p class=(counter.zero? ? "foo noitem" : "foo")
これは,
-
foo
クラスは必ずつける。 -
counter
がゼロのときのみnoitem
クラスをつける。
という意図だが,こんな分かりづらい書き方をすることはない。
クラス属性の二つの書き方は混在させられるので,
p.foo class=("noitem" if counter.zero?)
でいい。
拙文「Slim の属性値指定のちょっといい話 - Qiita」にもう少し詳しいことを書いた。
#{ }
を使おう
p = "氏名:#{name}"
式展開を書くためにわざわざ文字列オブジェクトにして =
で入れなくても,そのまま書けるって。
p 氏名:#{name}
次の形も OK。
p
| 氏名:#{name}
ただ,ちょっと注意して欲しい。Slim の #{ }
は,Ruby の式展開とは違って,中身の評価結果を文字列化して埋め込むときにエスケープする。
だからこの例で,修正前と修正後は等価ではない。
もっとも,この例ではエスケープするべきだろうから,修正後のほうが望ましいだろうけど。
もし,エスケープして欲しくない式を埋め込みたいなら #{{ }}
を使おう。
HTML タグを直に書いたほうが簡潔なことも
p
| 畳み込みには
code inject
| メソッドを使う。
インライン要素は,HTML タグを直接記述したほうが簡潔なこともある。
p 畳み込みには<code>inject</code>メソッドを使う。
このあたりは臨機応変に。
タグの直接記述のほうが良さそうに感じたら躊躇しなくていい。
子要素が一つなら階層構造が 1 行で書ける
header
h1 タイトル
header
の子要素は h1
ただ一つ。このような場合,コロン :
を使って 1 行で階層構造を記述することができる。
header: h1 タイトル
何階層でもネストできる。
コロンのあとのスペースは省略できない。
参考:inline tags
論理属性はどう書けば
input type="text" name="keyword" autofocus="autofocus"
短くするなら,以下のようないくつかの書き方ができる。
input type="text" name="keyword" autofocus=""
input type="text" name="keyword" autofocus=true
input[type="text" name="keyword" autofocus]
詳しくは拙文「Slim で autofocus のような論理属性を書く - Qiita」をどうぞ。
id か class のある div は要素名省略
div#wrapper
id
属性を持つ div
は,要素名を省略することができる。
#wrapper
class
属性を持つ div
も要素名を省略することができる。
div.signature
.signature
ただ,こちらは好みが分かれるかも知れない。ピリオドはインパクトに欠けるので,
.nav
.footer
のように要素名と紛らわしいクラス名を付けた場合,
nav
footer
と読み誤るかも知れない。
ある要素以下をコメントアウト
header
/h1.image-title
/ img src="title.png" alt="タイトル"
h1 タイトル
このような場合,img
は h1.image-title
より字下げしてあるので,スラッシュを置かなくても期待どおり消えてくれる。
header
/h1.image-title
img src="title.png" alt="タイトル"
h1 タイトル
詳しくは拙文「Slim で一部をまるごとコメントアウトする方法 - Qiita」をどうぞ。
属性値がヘルパーメソッド呼び出しだけ
script src="#{url_to 'js/common.js'}"
この例では,src
属性の値として,url_to
メソッドを呼び出している。(ちなみに Rails の例ではない)
しかし,わざわざ文字列リテラルの式展開の形にする必要は無い。Slim では属性値のところに Ruby の式が書けるので,以下でいい。
script src=url_to('js/common.js')
修正前では省略できていたメソッド引数の ( )
が省略できなくなったが,それでもこちらのほうが簡素でいいと思う。
ヘルパーを使って無駄な手動エスケープをやめよう
pre
|
<div>
foo
</div>
こんなコード誰も見たくないしメンテしたくないよね。
適当なヘルパーメソッドを作れば,以下のように <
などを文字参照(<
など)の形で書かなくて済むようになる。
== pre
|
<div>
foo
</div>
ヘルパーメソッドのつくり方は,Rails なのか何なのかによってちょっと違うとしても,だいたいこんな感じ:
def pre
%|<pre>#{Temple::Utils.escape_html(yield)}</pre>|
end
ここで,Temple::Utils.escape_html
というのは,slim gem が依存している temple gem が持っている HTML エスケープのメソッドです。好きなメソッドに置き換えてください。
上記の例では,pre
メソッドには
{"<div>\n froo\n</div>"}
というブロックが与えられたのと同じになる。インデントも期待どおりになっている。