テキスト内のURLがaタグに変換されるようにする
目的
タスク管理アプリのタスクの説明部分にリンクを追加できるようにしたい。
つまり、text_areaなどで入力したテキストを表示する際にURLを含んでいたら自動的にリンクを作るようにしたい、ということです。
helperメソッドを作成
URIライブラリを使います。
module ApplicationHelper require 'uri' def convert_url_into_a_tag(text) URI.extract(text, ['http', 'https']).uniq.each do |url| sub_text = "" sub_text << "<a href=" << url << " target=\"_blank\">" << url << "</a>" text.gsub!(url, sub_text) end return text end end
詳しい解説
URI.extract(text, ['http', 'https']).uniq.each do |url|
第一引数に与えられたテキスト(text)のなかから第二引数に与えられたスキーム名(httpとhttps)にマッチするものを探し出し、.uniq
で重複を削除してurlとしてブロックが受け取ります。
sub_text = "" sub_text << "<a href=" << url << " target=\"_blank\">" << url << "</a>" text.gsub!(url, sub_text)
ブロック内の処理は、用意した空のローカル変数sub_text
にそれぞれの文字列を追加していきtext.gsub!(url, sub_text)
でtext内のurlに該当する部分をsub_textに置き換えます。
注意
レシーバ.gsub(引数) → 置き換えを行った新しい文字列を返す
レシーバ.gsub!(引数) → レシーバ自身を置き換えて返す
最終的に、return text
で「URLをaタグに置き換えたテキスト(text)」を返します。
使い方
以下のように記述して使います。
<%= convert_url_into_a_tag(h(@task.description)).html_safe %>
h と html_safe
(h(@task.description)).html_safe
h
というのはhtml_escapeメソッドの略名で、HTMLタグなどをエスケープするメソッドです。
.html_safe
というのは、「レシーバに含まれる文字列は問題ないのでエスケープしないでね」というメソッドです。
2つは反対の意味を持つメソッドのようですが、なぜ一緒に使われているのでしょうか……
セキュリティ対策としてとても重要
まず、tasksコントローラから渡された@taskのdescription(タスクの説明文)から、html_escapeメソッドによってHTMLタグがエスケープされます。
これはユーザーが悪意のあるスクリプトを埋め込む事を防止する意味合いがあります。(クロスサイトスクリプティング=XSS)
そうしてXSSの対策をしたあとで、convert_url_into_a_tag
メソッドによってテキスト内のURLをaタグに置き換えます。
そのときにつけたHTMLタグは安全ですので、html_safe
メソッドで有効化する、という流れです。
ユーザーによる入力をエスケープした上で、改めてこちらでaタグを付与する ということですね。