💻

【Rails】検索機能まとめ

2023/10/02に公開

コントローラーの作成

ターミナル
rails g controller searches

ルーティング

route.rb
get "search" => "searches#search"

検索バーの作成

form_withヘルパーを使って作成を行います。

_form.html.erb
<% if user_signed_in? %>
  <%= form_with url: search_path, method: :get, local: true do |f| %>
    <%= f.text_field :word %>
    <%= f.select :model, options_for_select({"User" => "user","Book" => "book"}) %>
    <%= f.select :search,options_for_select({"完全一致" => "perfect", "前方一致" => "forward", "後方一致" => "backword", "部分一致" => "partial"}) %>
    <%= f.submit "検索" %>
  <% end %>
<% end %>
  1. url: search_pathと指定することで、ユーザーが入力した文字列をsearch_controllerのsearchアクションに送ります。データを取得したいのでmethod: :getを指定しています。
  2. f.text_field :wordとすることで、searchアクション側でparams[:word]を使って、入力した文字列を受け取れるようにします。:mode、:searchも同様です。
  3. options_for_selectを使って、プルダウンを作成します。表示されるのはUserとBookです。
    それぞれ=>でuser、bookが代入されています。
  4. 3.と同様に検索方法のプルダウンも記述しています。

部分テンプレート

ヘッダーの下に常に表示するよう記述します。
Bootstrapのクラス指定をして中央寄せ、マージンの調整をしています。

application.html.erb
<header>...</header>
.
.
<main>
  <div class="d-flex justify-content-center mb-2">
    <%= render "searches/form" %>
  </div>
  <%= yield %>
</main>
.
.

searchesコントローラー

serches_controller.rb
class SearchesController < ApplicationController
  before_action :authenticate_user!

  def search
    @model = params[:model]
    @word = params[:word]
    @search = params[:search]

    if @model == "user"
      @records = User.looks(@search, @word)
    else
      @records = Book.looks(@search, @word)
    end
  end

end
  1. フォームで取得した値を変数に代入します。
  2. if文の条件式を記述します。プルダウンの内容でUserモデルを参照するか、Bookモデルを参照するかが判断されます。
  3. looksメソッドを使って@search(検索条件)、@word(入力された文字列)から検索内容を取得し、@recordsに代入しています。

検索対象のモデルへの記述

プルダウンの検索方法を実装するための記述を行います。

user.rb
class User < ApplicationRecord
  def self.looks(search, word)
    if search == 'parfect'
      users = User.where("name Like?", "#{word}")
    elsif search == 'forward'
      users = User.where("name Like?", "#{word}%")
    elsif search == 'backward'
      users = User.where("name Like?", "%#{word}")
    else search == 'partial'
      users = User.where("name Like?", "%#{word}%")
    end
  end
end

1.self.looks(search, word)はlooksメソッドを呼び出すためのレシーバのselfとなっています。selfにはUserが入ります。引数はユーザーがフォームに入力した値を取得します。
2.whereメソッドを使って、条件の検索を行います。今回はUserモデルの中のnameカラムがそれぞれの条件で一致するように実装します。Like句を組み合わせることによって、各検索に適した実装ができます。

book.rb
class Book < ApplicationRecord
  def self.looks(search, word)
    if search == 'parfect'
      books = Book.where("title Like?", "#{word}")
    elsif search == 'forward'
      books = Book.where("title Like?", "#{word}%")
    elsif search == 'backward'
      books = Book.where("title Like?", "%#{word}")
    else search == 'partial'
      books = Book.where("title Like?", "%#{word}%")
    end
  end
end

Bookモデルも同様に記述します。titleはBookのカラムです。

検索結果の表示

search.html.erb
<% if @model == 'user' %>
  <h3>Users search for<%= @word %></h3>
  <%= render 'users/index', users: @records %>
<% else @model == 'book' %>
  <h3>Books search for<%= @word %></h3>
  <%= render 'books/index', books: @records %>
<% end %>

1.if文を用いて検索結果で表示する内容の分岐(プルダウンのUser又はBook)を行っています。
2.renderの変数を変更(@records)することにより、each文で並べた一覧の中の検索結果に合致したデータのみを表示する仕組みになっています。

参考にしたページ

Qiita
がんもさん

Discussion