🗂
【Rails】検索機能の作成
まだ先ですがポートフォリオの構想を練っていて、この機能は絶対に使うだろうな~と思い復習のため作成します。
実装する機能
コントローラ
- searchesコントローラ追加
- searchアクション追加
- 用途:検索を行う
ビュー
- ログインしている場合に限り、ヘッダー下部に検索窓・検索ボタンを設置すること
- 検索結果表示画面を作成し、検索結果を表示すること
- 検索対象(ユーザーか投稿か)の選択かをプルダウンメニューで選択できること
- 完全一致, 前方一致, 後方一致, 部分一致の検索手法をプルダウンメニューで選択できること
コントローラ作成
ターミナル
rails g controller searches
ルーティングの設定
config/routes.rb
Rails.application.routes.draw do
:
get "/search", to: "searches#search"
:
end
ビュー作成
検索バーの作成
検索バーは部分テンプレートにして作成します。
views/searches/_form.html.erb
<% 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| %>
フォームを作成するメソッド。検索内容をルーティングに送信してくれる。 -
<%= f.text_field :content %>
検索キーワードの入力用フィールドの表示と検索内容をcontent
にしてアクションに送る。 -
<%= f.select :model, options_for_select({"User" => "user", "Book" => "book"}) %>
モデルを選択するためのプルダウンメニュー、options_for_select
メソッドでUserモデルかBookモデルか選択できるようにしている。 -
<%= f.select :method, options_for_select({"完全一致" => "perfect", 以下省略}) %>
上記と同じ -
<%= f.submit "検索" %>
検索ボタンを表示
部分テンプレートの呼び出し
views/layouts/applictaion.html.erb
<!DOCTYPE html>
<html>
:
<body>
<%= render 'layouts/header' %>
<main>
<p id="notice"><%= notice %></p>
+ <div class="d-flex justify-content-center mb-2">
+ <%= render "searches/form" %>
+ </div>
<%= yield %>
</main>
<%= render 'layouts/footer' %>
</body>
</html>
ヘッダー下に常に表示されるように記述。
Bootstrapのクラス指定をして水平方向中央寄せ、下部に2単位のマージン調整をしています。
Searchesコントローラへの記述
controllers/searches_controller.rb
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 = Book.search_for(@content, @method)
end
end
end
解説↓
- 検索フォームからの情報
検索モデル →params[:model]
検索キーワード →params[:content]
検索方法 →params[: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
に代入する。
モデルへの記述
userモデル
models/user.rb
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
end
解説↓
-
def self.search_for(content, method)
content
は検索内容を表し、method
は検索方法を表しています。 - 以下の4つの条件分岐を表している
perfect
完全一致検索
forward
前方一致検索
backward
後方一致検索
partial
部分一致検索 -
where
メソッドを使いデータベースから該当データを取得し、変数に代入する。
where
メソッドにLIKE句を合わせ条件分岐を記述しています。LIKE句の記述例は下記のようになります。- 〜 WHERE 列名 LIKE '%検索値%'
- 〜 WHERE 列名 LIKE '検索値_'
- % → 0文字以上の任意の文字列
- _ → 任意の1文字
bookモデル
models/book.rb
class Book < ApplicationRecord
:
def self.search_for(content, method)
if method == 'perfect'
Book.where(title: content)
elsif method == 'forward'
Book.where('title LIKE ?', content + '%')
elsif method == 'backward'
Book.where('title LIKE ?', '%' + content)
else
Book.where('title LIKE ?', '%' + content + '%')
end
end
end
ちなみに僕はbookモデルに誤ってname
カラムを使用してしまいActiveRecord:Statementlnvalid
エラーが出てしまいました笑
お気を付けください!
以上
参考
Discussion