こんにちは、hachi8833です。今回はRails 5 Active SupportのString#html_safe
を見てみます。
今回のメソッド
- メソッド:
String#html_safe
および関連メソッド - ディレクトリ配置: rails/activesupport/lib/active_support/core_ext/string/output_safety.rb
条件
- Railsバージョン: 5-0-stable
- Rubyバージョン: 2.3.3
ソースのコメント等は適宜省略します。
html_safe
は「安全」であるとマーキングする
今回取り上げるString#html_safe
については、TechRachoの以前の記事『RailsビューのHTMLエスケープは#link_toなどのヘルパーメソッドで解除されることがある』も合わせてお読みいただくことをおすすめします。
html_safe
メソッドは対象が安全であることをマーキングし、以後エスケープを行わないようにするメソッドなので、安全であることが間違いなく確認できてから呼び出す必要があります。安全でないオブジェクトを安全にするものではありません。
また、ソースのコメントでも「このメソッドよりもsanitize
メソッドをおすすめする」と記載されています。
output_safety.rbの構成
output_safety.rbでは以下をrequireしています。
require 'erb'
require 'active_support/core_ext/kernel/singleton_class'
output_safety.rbは大きく分けて以下のような構成になっています。html_safe
は最後のStringクラスで定義されています。
- ERBクラス内でUtilモジュールを定義
- Objectクラス(
html_safe?
を定義) - Numericクラス(
html_safe?
を定義) - ActiveSupportモジュールでSafeBufferクラスを定義
- Stringクラス(
html_safe
を定義)
class ERB
module Util
...
end
end
class Object
def html_safe?
false
end
end
class Numeric
def html_safe?
true
end
end
module ActiveSupport #:nodoc:
class SafeBuffer < String
class SafeConcatError < StandardError
...
end
...
end
end
class String
def html_safe
ActiveSupport::SafeBuffer.new(self)
end
end
html_safe
html_safe
のコードそのものは以下の1行だけであり、ActiveSupport::SafeBufferオブジェクトを作成して返しています。ActiveSupport::SafeBuffer
クラスは同じファイルにあります。
class String
def html_safe
ActiveSupport::SafeBuffer.new(self)
end
end
ActiveSupport::SafeBuffer
は同じoutput_safety.rbファイルにあり、以下のメソッドがあります。
インスタンスメソッド
ここがhtml_safe
の中心となるメソッド群です。
initialize
メソッド[]
メソッドsafe_concat
メソッドinitialize_copy
メソッドclone_empty
メソッドconcat
メソッドprepend
メソッド+
メソッド%
メソッドhtml_safe?
メソッドto_s
メソッドto_param
メソッドencode_with
メソッド
たとえばconcat
メソッドは以下のように式展開のみエスケープして親クラスに渡しています。
def concat(value)
super(html_escape_interpolated_argument(value))
end
プライベートメソッド
- html_escape_interpolated_argumentメソッド
html_escape_interpolated_argument
は、html_safeでない式展開をエスケープします。