1. 一般的な「string interpolation」とは
まずは一般的な話から。プログラミング言語で文字列を出力するときに、文字列の一部を変数の値や式の評価結果に差し替えたいことが非常によくあります。
"信号: 赤"
"信号: 黄"
"信号: 青"
上の文字列リテラル(" "
で囲まれている部分)のうち、「赤」「黄」「青」を何らかの方法で変数から送り込んで差し替える操作を一般にstring interpolationと呼びます。
"信号: ●" # ←この●を「赤」「黄」「青」に差し替えたい
3つの文字列リテラルを使い分けるより、●を「赤」「黄」「青」だけ差し替える方が楽ですし、文字列リテラルが無駄に長くならずに済みます。
なお、次のような文字結合によるベタなやり方は、結果は同じでもstring interpolationとは呼ばれないようです。
● = "赤" # 「赤」「黄」「青」のいずれかが入る
"信号: " + ● #=> "信号: 赤" など
上はいずれも説明用の擬似言語であり、特定の言語ではありません。
他の言語でのstring interpolation
string interpolationは言語によってさまざまな構文があり、1つの言語に複数の構文があることもあります。置き換えの場所は「プレースホルダ(placeholder)」とも呼ばれます。
string interpolationは他の言語では多くの場合「文字列補間」という訳語が使われていますが、Rubyでは「式展開」と訳されるのが普通です。
他の言語では、以下もstring interpolationとだいたい同じ意味で使われます。
- 変数置換: variable interpolation
- 変数補間: variable substitution
- 変数置換: variable expansion
本記事では以後「式展開」で統一します。
Rubyの式展開とは
Rubyで文字列の式展開というと以下のような形で説明されることがよくあります。二重引用符" "
の中に#{ }
と変数を記述すると変数の値が展開されます。なお、式展開が効くのは二重引用符の中だけであり、一重引用符' '
の中では式展開は無効です。
year = "2019"
puts "Year: #{year}"
#=> Year: 2019
#{ }
の中にはRubyのどんな式でもそのまま書けます(引用符も書けます)。以下のようにリテラルも書こうと思えば書けますが、この形ではリテラルにする意味はないと思います。
puts "Year: #{'The last year of Heisei'}"
#=> Year: The last year of Heisei
Rubyの#{ }
では「#to_s
が自動的に効く」という重要な特性があります。このおかげで、#{ }
の中にどんな式を置いても文字列に変換されます。詳しくは以下をご覧ください。
式展開のバリエーション(1)
あまり使わないと思いますが、式展開#{}
の中に#
でコメントを書くこともできます。ただしその#
から行末の改行までがすべてコメントとみなされるため、式展開の閉じ}"
は次の行に書く必要があります。
puts "Year: #{year # 平成最後の年
}"
#=> Year: 2019
式展開のバリエーション(2)
これもあまり使わないと思いますが、式展開に入れる変数が$
で始まる変数(グローバル変数)や@
で始まる変数(インスタンス変数やクラス変数)の場合、#{}
の{}
を省略できます。
@year=2019
puts "Year: #@year"
#=> Year: 2019
式展開のバリエーション(3)
式展開#{}
の前にバックスラッシュ\
を置くと、式展開を抑制できます。
puts "Enter the \#{year}"
#=> Enter the #{year}
式展開のバリエーション(4)– %
を使う場合
%
記号を用いて、式展開と書式設定を一度に行うこともできます。書式設定のためのものなので、式展開と呼んでよいかどうかというのはありますが、利便性のためここに書きました。
puts "Year: %{year}" % { year: 2019 }
#=> Year: 2019
%
記号について詳しくは以下の記事をご覧ください。
参考: Rubyスタイルガイドでの引用符の使い分け
上述のとおり、Rubyでは二重引用符" "
の中で式展開が効き、一重引用符' '
の中では効きません。
RubocopのRubyスタイルガイド↓では、二重引用符と一重引用符をスタイル上使い分ける際にこの点も意識するとよいでしょう。
Railsで生SQLを書くときの?
による式展開
SQLを生書きするときに使える疑問符?
による式展開(プレースホルダ)はRubyではなく、Railsがサポートしている機能です。Railsでは?
ですが、プレースホルダの書式はWebフレームワークやRDBMSによって異なることがあります。
RailsのActive Recordでは、以下のように生SQLの中で変数を渡す箇所に?
を置き、カンマに続けて変数を書くことで、?
の部分に変数(この場合params[:name]
)が展開されます。このとき変数の内容が適切にサニタイズ(sanitize: 機能を持つ文字や式を安全のためにエスケープすること)されます。
Person.where('name = ? AND hidden_at IS NULL', params[:name])
ユーザーから受け取った文字列を変数として生SQLを書く場合、変数のサニタイズは必須です。さもないとSQLインジェクションという危険な脆弱性の原因となります(参考↓)。
RailsのActive Recordにはsanitize_sql_array
をはじめとするsanitize_sql_*
系メソッドがあります。生SQLを書く場合、特に変数を複数使う場合は、ぜひこれを使うべきです。
参考: ActiveRecord::Sanitization::ClassMethods
sanitize_sql_*
系メソッドは以前はprivateメソッドでしたが、Rails 5.2からはpublicになったので気兼ねなく使えます↓。
5.2からpublicやで https://t.co/lmuaeXnblI
— Ryuta Kamizono (@kamipo) August 8, 2018