LoginSignup
0
0

More than 1 year has passed since last update.

Ruby でヒアドキュメント内で条件分岐やループ処理を行う方法

Last updated at Posted at 2021-09-06

はじめに

複数行に渡る文字列を生成したいとき、ヒアドキュメントは便利だが、ヒアドキュメント内で条件分岐やループ処理を行う際に少し苦労したのでまとめておく。

実装方法

例として、以下のような仕様のコマンドラインスクリプトを実装してみる。

  • マークダウンで記述されるブログ記事に、自動で YAML ヘッダをつける機能を持つ
  • 引数としてタイトルやサムネイル画像、タグを与えると、@options 変数で各引数の値を取得できる

その際の、YAML ヘッダをヒアドキュメントで記述する。

require 'erb'

header = <<~'HEADER'
  ---
  layout: post
  title: "<%= @options[:title] %>"
  image: "<%= @options[:image] %>"
  date: "<%= Time.now.strftime('%Y-%m-%d') %>"
  tags:
  <%- @options[:tags]&.each do |tag| -%>
  - <%= tag %>
  <%- end -%>
  ---
HEADER

puts ERB.new(header, nil, '-').result(binding)

\n を実際の改行に変換した結果は以下のように出力される。

---
layout: post
title: "Hello world!"
image: "/images/2021/09/hello_world.png"
date: "2021-09-06 22:37:34"
tags:
- greeting
- first-post
---

解説

ヒアドキュメント内で条件分岐やループ処理を行いたい場合は ERB を使用する。

  • <%--%> で囲まれた箇所で Ruby が実行される
  • <%=%> で囲まれた箇所は Ruby が実行された際の戻り値が出力される

上記 2 つのどちらも、囲まれた箇所で Ruby が実行されるが、違いとしては出力結果がそのまま表示されるかされないかだ。

@options[:tags]&.each do |tag|end の部分は、結果を出力するわけではなく、単に Ruby を実行してほしいだけなので <%--%> で囲む。

trim_mode について

なお、<%--%> の記法は ERB のインスタンスを生成する際の第 3 引数に '-' を指定することで使用可能となる。これは trim_mode と呼ばれる。

# 第 3 引数に '-' を指定
ERB.new(header, nil, '-').result(binding)

trim_mode を使わずに、ヒアドキュメントの出力のみを引数に指定するならば、以下のように記述することもできる。

require 'erb'

erb = ERB.new <<~'HEADER'
  ---
  layout: post
  title: "<%= @options[:title] %>"
  image: "<%= @options[:image] %>"
  date: "<%= Time.now.strftime('%Y-%m-%d') %>"
  tags:
  <% @options[:tags]&.each do |tag| %>
  - <%= tag %>
  <% end %>
  ---
HEADER

puts erb.result(binding)

ERB インスタンス生成時の第 1 引数に直接ヒアドキュメントを渡す書き方だ。trim_mode を用いないので <%--%> ではなく <%%> を使用している。

この場合、出力が以下のようになる。

---
layout: post
title: "Hello world!"
image: "/images/2021/09/hello_world.png"
date: "2021-09-06 22:43:28"
tags:

- greeting

- first-post

---

余計な空行が出力されてしまっている。これは <% @options[:tags]&.each do |tag| %> の部分と <% end %> の部分が、行としては存在しているが、何も出力されないためである。

このように、ただ Ruby のコードを実行させたいだけの行でも、存在している以上は出力結果に反映されてしまう。

これを解決するのが trim_mode である。今回の例では第 3 引数に - を指定したので <%%> の代わりに <%--%> を使うことで、余計な改行が入らなくなる。

trim_mode についての詳細は ERB のリファレンスマニュアル を参照すること。

弱点

ERB を使用するとヒアドキュメント内で条件分岐やループ処理を行うことができるが、以下のデメリットがある。

  • シンタックスエラーが発生した際に、行数が若干わかりづらい

ERB を用いたヒアドキュメント内でシンタックスエラーが発生すると、そのエラーが発生した箇所が、ヒアドキュメント内の行数で表示される。ファイルの行数ではない。

そのため、ぱっと見で何行目にシンタックスエラーがあるのかがわからない。あまりヒアドキュメントが長くなりすぎると、シンタックスエラーが発生した際の追跡が難しくなる点に注意すること。

参考

0
0
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
0
0