LoginSignup
14
7

More than 5 years have passed since last update.

SQL の記述に ERB を使う

Last updated at Posted at 2017-09-13

はじめに

Rails などで Active Record を使っていても生の SQL を記述したいケースはままあります。その際に SQL ファイル内に変数や条件分岐を埋め込めると便利です。そこで、今回 ERB テンプレートを使って実現してみました。

特定の条件下のみ WHERE 句を使うというケースを想定しています。

方法 1: ERB を使う

sample1.sql.erb
SELECT
  characters.name,
  animes.title
FROM
  characters
  INNER JOIN anime_characters
    ON anime_characters.character_id = characters.id
  INNER JOIN animes
    ON animes.id = anime_characters.anime_id
<% if defined?(:title) %>
WHERE
  animes.title = '<%= title %>'
<% end %>
;
require 'erb'

# 第 3 引数を指定しないと <%= %> の行が空行として出力されてしまう。
template1 = ERB.new(File.read('sample1.sql.erb'), nil, '<>')

puts(template1.result(binding))
#=> NameError: undefined local variable or method `title' for main:Object

title = '偽物語'
puts(template1.result(binding)) # 出力結果は stdout2

title = nil
puts(template1.result(binding)) # 出力結果は stdout1
stdout1
SELECT
  characters.name,
  animes.title
FROM
  characters
  INNER JOIN anime_characters
    ON anime_characters.character_id = characters.id
  INNER JOIN animes
    ON animes.id = anime_characters.anime_id
;
stdout2
SELECT
  characters.name,
  animes.title
FROM
  characters
  INNER JOIN anime_characters
    ON anime_characters.character_id = characters.id
  INNER JOIN animes
    ON animes.id = anime_characters.anime_id
WHERE
  animes.title = '偽物語'
;

ERB#result には Binding オブジェクトを渡す必要があります。通常 Kernel.#binding を渡しますが、できれば ERB テンプレート描画時に必要な値のみを渡したいです。

方法 2: Tilt を使う

$ gem install tilt
sample2.sql.erb
SELECT
  characters.name,
  animes.title
FROM
  characters
  INNER JOIN anime_characters
    ON anime_characters.character_id = characters.id
  INNER JOIN animes
    ON animes.id = anime_characters.anime_id
<% if locals.key?(:title) %>
WHERE
  animes.title = '<%= title %>'
<% end %>
;
require 'erb'
require 'tilt'

template2 = Tilt.new('sample2.sql.erb')

puts(template2.render(nil)) # 出力結果は stdout1 と同じ
puts(template2.render(nil, title: '偽物語')) # 出力結果は stdout2 と同じ

Tilt#render の第 2 引数に渡した hash は、ERB テンプレート中では locals という変数で参照できます。

参考

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