ステップ 1: searches
コントローラの作成
まず、検索専用のコントローラを作成し、ユーザーや投稿(Book)の検索ロジックを実装します。
rails g controller searches
-
rails g controller searches
: 検索機能用のコントローラを作成します。このコントローラで検索処理を行います。
コントローラの中身 (app/controllers/searches_controller.rb
)
class SearchesController < ApplicationController
before_action :authenticate_user! # ログインしているユーザーのみが検索可能にする
def search
@model = params[:model] # 検索対象("user" か "book")を取得するための変数
@search_method = params[:search_method] # 検索方法(完全一致、部分一致など)を取得するための変数
@query = params[:query] # ユーザーが入力した検索ワードを取得
# 検索対象がユーザーの場合
if @model == "user"
@results = search_for_user(@search_method, @query) || [] # ユーザーを検索し、結果を@resultsに格納。結果がなければ空の配列を返す
# 検索対象が投稿(Book)の場合
elsif @model == "book"
@results = search_for_book(@search_method, @query) || [] # 投稿(Book)を検索し、結果を@resultsに格納。結果がなければ空の配列を返す
else
@results = [] # モデルが指定されていない場合は空の配列を返す
end
end
private
# ユーザーを検索するメソッド。検索方法によって異なるクエリを実行
def search_for_user(search_method, query)
case search_method
when "perfect" # 完全一致検索
User.where(name: query) # ユーザー名が完全に一致するものを検索
when "forward" # 前方一致検索
User.where("name LIKE ?", "#{query}%") # ユーザー名が指定した文字列で始まるものを検索
when "backward" # 後方一致検索
User.where("name LIKE ?", "%#{query}") # ユーザー名が指定した文字列で終わるものを検索
when "partial" # 部分一致検索
User.where("name LIKE ?", "%#{query}%") # ユーザー名のどこかに指定した文字列が含まれるものを検索
end
end
# 投稿(Book)を検索するメソッド。検索方法によって異なるクエリを実行
def search_for_book(search_method, query)
case search_method
when "perfect" # 完全一致検索
Book.where(title: query) # タイトルが完全に一致する投稿を検索
when "forward" # 前方一致検索
Book.where("title LIKE ?", "#{query}%") # タイトルが指定した文字列で始まる投稿を検索
when "backward" # 後方一致検索
Book.where("title LIKE ?", "%#{query}") # タイトルが指定した文字列で終わる投稿を検索
when "partial" # 部分一致検索
Book.where("title LIKE ?", "%#{query}%") # タイトルのどこかに指定した文字列が含まれる投稿を検索
end
end
end
ステップ 2: ルーティング設定
検索機能用のルートを設定します。
config/routes.rb
get 'search', to: 'searches#search', as: 'search'
-
get 'search'
:GET
リクエストで/search
というURLにアクセスした際、searches#search
アクションを実行するルートを設定します。 -
to: 'searches#search'
:searches
コントローラのsearch
アクションを実行する指定です。 -
as: 'search'
: 名前付きルートsearch_path
を作成し、ビューでこのルートを参照できます。
ステップ 3: 検索フォームの作成
検索フォームを作成し、ユーザーが検索ワードを入力したり、検索対象や検索方法を選べるようにします。
検索フォームのコード(app/views/layouts/_header.html.erb
など)
<% if user_signed_in? %> <!-- ユーザーがログインしている場合のみ表示 -->
<%= form_with url: search_path, method: :get, local: true do %> <!-- 検索フォーム。送信先は`search_path`で、GETリクエストを送る -->
<%= text_field_tag :query, params[:query], placeholder: "検索ワードを入力" %> <!-- 検索ワードの入力フィールド -->
<%= select_tag :model, options_for_select([["User", "user"], ["Book", "book"]]), prompt: "検索対象を選択" %> <!-- 検索対象(ユーザー or 投稿)を選択するプルダウンメニュー -->
<%= select_tag :search_method, options_for_select([["完全一致", "perfect"], ["前方一致", "forward"], ["後方一致", "backward"], ["部分一致", "partial"]]), prompt: "検索方法を選択" %> <!-- 検索方法(完全一致、部分一致など)を選ぶプルダウンメニュー -->
<%= submit_tag "検索" %> <!-- 検索ボタン -->
<% end %>
<% end %>
フォーム内の解説
-
form_with
: Railsでフォームを作成するためのヘルパーです。url: search_path
でフォームの送信先を指定し、GET
リクエストを使用しています。 -
text_field_tag
: ユーザーが入力する検索ワードのテキストフィールドです。params[:query]
に入力内容が送られます。 -
select_tag :model
: 検索対象(ユーザー or 投稿)を選択するためのプルダウンメニューです。 -
select_tag :search_method
: 検索方法(完全一致、部分一致など)を選択するプルダウンメニューです。 -
submit_tag
: 検索を実行するためのボタンです。
ステップ 4: 検索結果の表示
検索結果を表示するためのビューを作成します。ユーザー名や投稿タイトルをリスト形式で表示します。検索結果がない場合は、該当する結果がない旨を表示します。
検索結果の表示(app/views/searches/search.html.erb
)
<h2>検索結果</h2>
<% if @results.any? %> <!-- 結果が1件でもある場合 -->
<% @results.each do |result| %> <!-- 検索結果を1つずつ表示 -->
<% if @model == "user" %> <!-- 検索対象がユーザーの場合 -->
<td>
<%= image_tag result.get_profile_image, size: '100x100' %> <!-- プロフィール画像を表示 -->
</td>
<td>
<%= link_to result.name, user_path(result) %> <!-- ユーザー名をリンクとして表示 -->
</td>
<% elsif @model == "book" %> <!-- 検索対象が投稿(Book)の場合 -->
<td>
<%= link_to result.title, book_path(result) %> <!-- 投稿タイトルをリンクとして表示 -->
</td>
<% end %>
<% end %>
<% else %> <!-- 結果が1件もない場合 -->
<p>該当する結果がありませんでした。</p> <!-- 該当する結果がないことを表示 -->
<% end %>
検索結果表示の解説
-
@results.any?
: 検索結果が1件でもあるかを確認します。1件以上ある場合は結果を表示します。 -
@results.each do |result|
: 検索結果をループで1件ずつ処理し、表示します。 -
@model == "user"
: 検索対象がユーザーの場合、ユーザー名を表示します。user_path(result)
でユーザー詳細ページへのリンクも設定しています。 -
@model == "book"
: 検索対象が投稿(Book)の場合、投稿タイトルを表示し、book_path(result)
で投稿詳細ページへのリンクを設定しています。