A Day in the Life

Rails3 での自動文字列エスケープの挙動

Rails3 での自動文字列エスケープの挙動

興味があったのでちょっと実装のぞいてみた。

Rails3 では、テンプレートで標準で文字列をHTMLエスケープするようになってる。

<%= "test" %> #=> エスケープされる

これを自動エスケープをやめるには

<%= raw "test" %> #=> エスケープされない

となるんだけど、たとえば以下のように h() でエスケープした文字列と通常の文字列を連結するとどちらもエスケープされる。

<%= h("test") + "secure string" %> # どちらのタグもエスケープされる

これを回避するには

<%= h("test").safe_concat("secure string") %>
<%= h("test") + "secure string".html_safe %>

としてやればよい。Rails3 (のActiveSupport) では、はたしてその文字が html のタグを含んでいても安全かどうかを調べるフラグ String#html_safe? が利用できるため、h() でエスケープしたり、"この文字列はまんま表示しても安全だよ" と明示的に String#html_safe を利用して ActiveSupport::SafeBuffer のクラスへ変換することで、そのまんまタグを表示することができる。

また、安全かどうかちゃんとフラグで持ってるため

h( h( "" ) )

としても一回目の h() で安全となるため自動で判断され多重エスケープされるケースがほぼ無くなる、というメリットも。