LoginSignup
76
71

More than 3 years have passed since last update.

Slim コードのリファクタリング

Last updated at Posted at 2016-09-15

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 だけでなくクラスも同様。

詳細は以下参照:
Add support for slashes w/ digits and colons in class / id names by thewatts · Pull Request #841 · slim-template/slim

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 タイトル

このような場合,imgh1.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
  |
    &lt;div&gt;
      foo
    &lt;/div&gt;

こんなコード誰も見たくないしメンテしたくないよね。

適当なヘルパーメソッドを作れば,以下のように < などを文字参照(&lt; など)の形で書かなくて済むようになる。

修正後
== 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>"}

というブロックが与えられたのと同じになる。インデントも期待どおりになっている。

76
71
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
76
71