【Rails】検索機能
本の投稿サイトに検索機能をgemを使わずに実装します。
実装機能の要件
実装機能の要件は以下の通り。
コントローラー | アクション | 用途 |
---|---|---|
SearchesController | search | 検索を行う |
ビュー: ヘッダー
- ログインしている場合に限り、ヘッダーに検索窓・検索ボタンを設置。
- 検索対象(ユーザーか投稿か)の選択かをプルダウンメニューで選択できること。
- 完全一致, 前方一致, 後方一致, 部分一致の検索手法をプルダウンメニューで選択できること。
ビュー: 検索結果表示画面
- 検索結果表示画面を作成し、検索結果を表示すること。
Controller作成
ターミナルで以下のコマンドを実行してコントローラを作成します。
rails g controller searches
Routingの設定
以下の通り検索機能にアクセスするためのルーティングを設定をします。
Rails.application.routes.draw do
: #省略
get "/search", to: "searches#search"
end
Viewの作成
- 検索ボックスの作成:
<% if user_signed_in? %>
<%= form_with url: search_path, method: :get, local: true do |f| %>
<%= f.text_field :content %>
<%= f.select :model, options_for_select({"User" => "user", "Book" => "book"}) %>
<%= f.select :method, options_for_select({"完全一致" => "perfect", "前方一致" => "forward", "後方一致" => "backward", "部分一致" => "partial"}) %>
<%= f.submit "検索" %>
<% end %>
<% end %>
解説:
-
<% if user_signed_in? %>
ユーザーがログインしているかどうかをチェックしています。ログインしている場合のみ検索フォームを表示します。 -
<%= form_with url: search_path, method: :get, local: true do |f| %>
フォームを作成するためのメソッドです。search_path
に対してGET
メソッドでフォームのデータを送信します。 -
<%= f.text_field :content %>
検索キーワードを入力するためのテキストフィールドを表示します。:content
は検索キーワードのパラメータ名を指定しています。 -
<%= f.select :model, options_for_select({"User" => "user", "Book" => "book"}) %>
検索対象のモデルを選択するためのプルダウンメニューを表示します。:model
は選択したモデルのパラメータ名を指定しています。options_for_select
メソッドは、選択肢のハッシュを受け取り、プルダウンメニューを作ります。 -
<%= f.select :method, options_for_select({"完全一致" => "perfect", "前方一致" => "forward", "後方一致" => "backward", "部分一致" => "partial"}) %>
検索方法を選択するためのプルダウンメニューを表示します。 -
<%= f.submit "検索" %>
は、検索ボタンを表示します。ユーザーが入力した情報を送信するために使用します。
- 部分テンプレートの呼び出し:
<!DOCTYPE html>
<html>
:
<body>
<%= render 'layouts/header' %>
<main>
<%= flash[:notice] %>
+ <div class="d-flex justify-content-center mb-2">
+ <%= render "searches/form" %>
+ </div>
<%= yield %>
</main>
<%= render 'layouts/footer' %>
</body>
</html>
解説:
-
d-flex
フレックスコンテナを作成するためのクラスです。 -
justify-content-center
水平方向に中央揃えを行うためのクラスです。 -
mb-2
: 下部に2単位のマージンを追加します。
完成:
以下のような検索ボックスができます。
Searchesコントローラへの記述
以下の通り記述します。
class SearchesController < ApplicationController
before_action :authenticate_user!
def search
@model = params[:model]
@content = params[:content]
@method = params[:method]
# 選択したモデルに応じて検索を実行
if @model == "user"
@records = User.search_for(@content, @method)
else
@records = Books.search_for(@content, @method)
end
end
end
解説:
以下にsearch
アクションについて解説します。
-
@model = params[:model]
ユーザーが選択した検索対象のモデル("user" または "book")を@model
変数に代入しています。 -
@content = params[:content]
ユーザーが入力した検索キーワードを@content
変数に代入しています。 -
@method = params[:method]
ユーザーが選択した検索方法("perfect"、"forward"、"backward"、"partial")を@method
変数に代入しています。 -
if @model == "user"
: 選択されたモデルが "user" である場合の条件分岐です。ユーザーの検索を行います。 -
@records = User.search_for(@content, @method)
選択された検索対象(ユーザー)に対して、search_for
メソッドを呼び出して検索を実行し、結果を@records
変数に代入します。 -
else
: 上記の条件に当てはまらない場合の条件分岐です。"book"の検索を行います。 -
@records = Books.search_for(@content, @method)
選択された検索対象(書籍)に対して、search_for
メソッドを呼び出して検索を実行し、結果を@records
変数に代入します。
Modelへの追記
Modelファイルに検索機能を追加していきます。
Userモデル:
class User < ApplicationRecord
:
def self.search_for(content, method)
if method == 'perfect'
User.where(name: content)
elsif method == 'forward'
User.where('name LIKE ?', content + '%')
elsif method == 'backward'
User.where('name LIKE ?', '%' + content)
else
User.where('name LIKE ?', '%' + content + '%')
end
end
:
Bookモデル:
class Book < ApplicationRecord
:
def self.search_for(content, method)
if method == 'perfect'
Book.where(title: content)
elsif method == 'forward'
Book.where('name LIKE ?', content + '%')
elsif method == 'backward'
Book.where('name LIKE ?', '%' + content)
else
Book.where('name LIKE ?', '%' + content + '%')
end
end
:
解説:
- このコードは、
content
とmethod
という2つのパラメータを受け取ります。content
は検索内容を表し、method
は検索方法を表します。 -
method
の値に応じて以下の4つの条件分岐を行います。
-
perfect
: 完全一致検索。content
と完全に一致するタイトルを持つレコードを検索します。 -
forward
: 前方一致検索。content
で指定された文字列で始まるタイトルを持つレコードを検索します。 -
backward
: 後方一致検索。content
で指定された文字列で終わるタイトルを持つレコードを検索します。 -
partial
: 部分一致検索。content
で指定された文字列を含むタイトルを持つレコードを検索します。
whereメソッド・LIKE演算子について
別記事で解説しているので参考までに。
検索結果表示Viewの作成
<% if @model == 'user' %>
<h3>Users search for "<%= @content %>"</h3>
<%= render 'users/index', users: @records %>
<% elsif @model == 'book' %>
<h3>Books search for "<%= @content %>"</h3>
<%= render 'books/index', books: @records %>
<% end %>
解説:
@model
の値に応じて、検索結果の見出しと一覧表示を条件分岐しています。
-
@model
が'user'
の場合、ユーザーの検索結果を表示します。 -
@model
が'book'
の場合、書籍の検索結果を表示します。
完成:
"がんも"とUser検索すると、以下のような画面が表示されます。
以上、検索機能の実装でした。
gemの Ransack を使うと簡単に検索フォームを実装できるみたい。
続きはこちら。
Discussion
大変参考になりました!
貴重な共有をありがとうございます!
すぎさん、こちらこそ嬉しいコメントありがとうございます😊
参考になったなら本当に嬉しい限りです😭
学びのアウトプット、必ず力になっていきますのでお互い頑張りましょうね♪