虎の穴開発室ブログ

虎の穴ラボ株式会社所属のエンジニアが書く技術ブログです

MENU

Thymeleaf で 条件式を繰り返さない書き方

Thymeleafで条件式を繰り返さない書き方 こんにちは、おおばです。普段は、SEO関連の案件に携わっております。

Thymeleaf でif - unless文や三項演算子を繰り返し記述せず、簡潔に記述する方法を見つけたので紹介致します。

Thymeleafでネストが深くなりがちになる理由

直近の開発案件で、Thymeleafでリクエストパラメータに応じてHTMLタグを出し分けたい場面に遭遇しました。

試しに実装してみると、Thymeleaf特有の「フラグメント内のスコープでしか利用できる変数しか無い(th:with)」、「ループ処理中に(th:each) 抜けること(break)が出来ない」といった仕様から、if文のネストが深いコードが誕生してしまいました。

ThymeleafにはSwitch文があるものの、基本的にはth:switchには変数を指定するので、 リクエストパラメータの値を順繰りチェックする事が出来ませんでした。

<div th:switch="${user.role}">
  <p th:case="'admin'">User is an administrator</p>
  <p th:case="#{roles.manager}">User is a manager</p>
</div>

Tutorial: Using Thymeleaf (ja) [7.2 スイッチ文]より引用 Tutorial: Using Thymeleaf (ja)

条件式を繰り返す書き方

例として、リクエストパラメータの存在有無に応じてtitleを出し分けたいとします。

if - unlessが1階層のコードです。この段階では、まだスッキリして読みやすいです。

<th:block th:if="${!#strings.isEmpty(param.hoge)}">
    <title>true:hoge</title>
</th:block>
<th:block th:unless="${!#strings.isEmpty(param.hoge)}">
    <title>false:hoge</title>
</th:block>

更に1階層深くネストすることで、一気に可読性が下がる事が見て取れます。

<th:block th:if="${!#strings.isEmpty(param.hoge)}">
   <title>true:hoge</title>
</th:block>
<th:block th:unless="${!#strings.isEmpty(param.hoge)}">
    <th:block th:if="${!#strings.isEmpty(param.fuga)}">
        <title>true:fuga</title>
    </th:block>
    <th:block th:unless="${!#strings.isEmpty(param.fuga)}">
        <title>false:hogefuga</title>
    </th:block>
</th:block>

これを繰り返すと非常に可読性が低いコードになってしまうのは明白ですね。

Googleで検索したところ似たような悩みを持っている方がちらほら見受けられましたが、 if文の代わりに三項演算子をゴリゴリ書くといった解決策しか見つけることが出来ませんでした。

条件式を繰り返さない書き方

switch文と三項演算子を組み合わせることで、isEmptyが不要になり簡潔に記述出来ます。

<th:block th:switch="文字列">
   <title th:case="${param.hoge}?文字列">true:hoge</title>
   <title th:case="${param.fuga}?文字列">true:fuga</title>
</th:block>

ここで指定する文字列は一致すれば何でもOKです。 switchの合致条件として明示的にtrueを指定することで、様々なメソッドに対応可能です。

<th:block th:switch="true">
   <title th:case="${#strings.contains(param.hoge,'hoge')}">true:hoge</title>
   <title th:case="${#strings.contains(param.fuga,'fuga')}">true:fuga</title>
</th:block>

switch文での合致条件に[文字列]及び[true]を明示的に指定することで、多重構造のif文と同じことが出来るというのが今回のミソです。

Thymeleafを書いていて闇に飲まれそうなときの光になれば幸いです。

P.S.

11/26(火)には記念すべき10回目となるLT会を秋葉原アーツ千代田3331で開催します! 発表者枠、参加者枠ともにまだ空きがありますので是非ご応募ください! yumenosora.connpass.com

虎の穴では一緒に働く仲間を絶賛募集中です! この記事を読んで、興味を持っていただけた方はぜひ弊社の採用情報をご覧下さい。 yumenosora.co.jp