Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Railsの技: highlightヘルパーで検索結果を強調表示する(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

日本語タイトルは内容に即したものにしました。

Railsの技: highlightヘルパーで検索結果を強調表示する(翻訳)

Railsのhighlightヘルパーで、以下のように検索結果のマッチ部分を<mark>タグでラップします。

通知リストの"comment"という語の検索結果をハイライトする

使い方

検索する語をparams経由でコントローラに渡し(params[:search]など)、これを用いて結果をフィルタします。

# app/controllers/inbox_controller.rb
class InboxController < ApplicationController
  def index
    @notifications = Current.user.notifications.for_search(params[:search])
  end
end
# app/models/notification.rb
class Notification < ApplicationRecord
  belongs_to :recipient, class_name: "User"

  validates :message, presence: true

  def self.for_search(term)
    if term.present?
      # Implement searching however you'd like
      where("message ILIKE ?", "%#{term}%")
    else
      all
    end
  end
end

以下のように@notificationsをレンダリングし、TextHelper#highlightでメッセージのクエリにマッチする部分を強調表示します。

<% @notifications.each do |notification| %>
  <%= link_to highlight(notification.message, params[:search]), notification %>
<% end %>

<mark>タグには自由にスタイルを付けられます。

mark {
  background-color: yellow;
}

オプション

highlightには、マッチするフレーズとして「文字列」「配列」「正規表現」のどれでも渡せます。マッチでは大文字小文字を区別しません。

# 文字列の場合
highlight('Boring Rails is the best', 'rails')
# => Boring <mark>Rails</mark> is the best

# 正規表現の場合
highlight('Boring Rails is the best', /rails|best/)
# => Boring <mark>Rails</mark> is the <mark>best</mark>

# 配列の場合
highlight('Boring Rails is the best', ['is', 'best'])
# => Boring Rails <mark>is</mark> the <mark>best</mark>

マッチしない場合やフレーズが空の場合でも問題なく動作します。

highlight('Boring Rails is the best', 'JavaScript')
# => Boring Rails is the best

highlight('Boring Rails is the best', '') # nil works too
# => Boring Rails is the best

ハイライトオプションを渡して、マッチした部分の周りのHTMLマークアップをオーバーライドすることも可能です。マッチを参照する\1を使います。出力はデフォルトでサニタイズ(危険な文字列を除去すること)されます。

highlight('Boring is best', 'best', highlight: '<b>\1</b>')
# => Boring is <b>best</b>

highlight('Boring is best', 'best', highlight: '<a href="tagged?q=\1">\1</a>')
# => Boring is <b>best</b>

追加コードを実行する必要がある場合は、レンダリングを行うブロックを以下のように渡せます。

highlight('Blog: Boring Rails', 'rails') do |match|
  link_to(match, public_share_path(term: match))
end
# => Blog: Boring <a href="/public/share?term=Rails">Rails</a>

参考資料

関連記事


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。