(更新版)テキスト内のURLをリンク化する(Rails 総復習1ヶ月チャレンジ 14日目(番外編))

またしてもお久しぶりの更新となってしまいました!
今回は先日書いた下記の記事
テキスト内のURLをリンク化する(Rails 総復習1ヶ月チャレンジ 10日目(番外編)) - yama2_0506’s diary
この内容を共同開発サイトで実装させていただいていたのですが、ある特定の条件下でバグが起きてしまうので改めて修正版を記載したいと思います!

バグについて

同一ホスト名のURLを重複して貼るとバグが出てしまっておりました。
こんな感じ↓
f:id:yama2_0506:20211021092021p:plain

訂正版コード

まずは訂正版のコードからです。

#app/helpers/application_helper.rb
def text_url_to_link(text)
  require 'uri'
  uri_reg = URI.regexp(%w[http https])
  return text.gsub(uri_reg) {"<a href='#{$&}' target='_blank'\>#{$&}</a>"}
end

訂正前と見比べてみましょう。

def text_url_to_link(text)
  URI.extract(text, ['http', 'https']).uniq.each do |url|
    sub_text = "<a href=#{url} target=\'_blank\'>#{url}</a>"
    text.gsub!(url, sub_text)
  end
  return text
end

以前はURI.extractを使いURL形式の文字列を全て取得し、それをeachで回し処理をしておりました。
ほとんどの場合はこれで問題なく動くのですが、同一ホスト名のURLがtextに入っていた場合、先にaタグに変換されていたtextに対して置換処理が行われてしまいバグが発生します。

コード解説

コード解説をしていきます。

URI.regexp(%w[http https])

URI.regexpでURLパターンにマッチする正規表現を取得しています。
参考:URI.regexp (Ruby 3.0.0 リファレンスマニュアル)

return text.gsub(uri_reg) {"<a href='#{$&}' target='_blank'\>#{$&}</a>"}

gsubで正規表現にマッチした文字列をaタグに置換しています。
$&にはgsubを使ってtext内の文字列に正規表現にマッチした部分文字列が代入されます。$&は正規表現によるマッチが行われるたびにマッチした部分文字列が都度上書きされ、正規表現が文字列にマッチしなかった時にはnilが代入されます。

参考:
String#gsub (Ruby 3.0.0 リファレンスマニュアル)

マッチした文字列を取得($&) - 後方参照 - Ruby正規表現の使い方

今回は以上です!