1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】検索機能の実装※自己振り返り用

Posted at

ステップ 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)で投稿詳細ページへのリンクを設定しています。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?