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?

More than 1 year has passed since last update.

検索機能

Posted at

:shamrock: 前提条件

・バージョン rails 6.1.7
・device導入 ・Bootstrap導入
・ユーザー機能実装済(Userモデル)
・投稿機能実装済(Bookモデル)

.検索対象(ユーザーか投稿か)の選択かをプルダウンメニューで選択できること
・完全一致, 前方一致, 後方一致, 部分一致の検索手法をプルダウンメニューで選択できること
・検索後は、検索結果一覧ページを表示します。


:shamrock: ルーティング

routes.rb
 get 'searche' => 'searches#search'

:shamrock: モデル

user.rb
# 検索方法分岐 (nameは検索対象であるusersテーブル内のカラム名)
  def self.looks(search, word)
    if search == "perfect_match"
      @user = User.where("name LIKE?", "#{word}")
    elsif search == "forward_match"
      @user = User.where("name LIKE?","#{word}%")
    elsif search == "backward_match"
      @user = User.where("name LIKE?","%#{word}")
    elsif search == "partial_match"
      @user = User.where("name LIKE?","%#{word}%")
    else
      @user = User.all
    end
  end
book.rb
  # 検索方法分岐 (titleは検索対象であるbooksテーブル内のカラム名)
  def self.looks(search, word)
    if search == "perfect_match"
      @book = Book.where("title LIKE?","#{word}")
    elsif search == "forward_match"
      @book = Book.where("title LIKE?","#{word}%")
    elsif search == "backward_match"
      @book = Book.where("title LIKE?","%#{word}")
    elsif search == "partial_match"
      @book = Book.where("title LIKE?","%#{word}%")
    else
      @book = Book.all
    end
  end

:point_up:looksメソッドは、検索方法(完全一致、前方一致、後方一致、部分一致)と検索ワードを元にユーザーを検索します。

完全一致("perfect_match"): 検索ワードと(ユーザー、本)名が全く同じユーザーを探します。
前方一致("forward_match"): 検索ワードで始まる(ユーザー、本)名を持つユーザーを探します。
後方一致("backward_match"): 検索ワードで終わる(ユーザー、本)名を持つユーザーを探します。
部分一致("partial_match"): 検索ワードを含む(ユーザー、本)名を持つユーザーを探します。
それ以外: 全てのユーザーを返します。

:star:User.where("name LIKE?", "#{word}%")
のような形で、SQLのLIKE検索を使って、条件に一致するものをデータベースから探し出します。


:shamrock: コントローラー作成

searchesコントローラーを作成します。

rails g contoroller searches

アクションの定義

searches_controller.rb
class SearchesController < ApplicationController
  before_action :authenticate_user!
  
  def search_result
    @range = params[:range]
    
    if @range == "User"
      @users = User.looks(params[:search], params[:word])
    else
      @books = Book.looks(params[:search], params[:word])
    end
  end
end

:snowflake:before_action :authenticate_user!
ユーザーがログインしていることを確認しています。これにより、ログインしていないユーザーが検索を使用することを防ぎます。

:snowflake:@range = params[:range]
検索範囲(ユーザーまたは本)を@rangeという変数に保存します。

:snowflake:if @range == "User": 検索範囲が"User"かの確認。
@users = User.looks(params[:search], params[:word])
もし範囲が"User"なら、Userモデルのlooksメソッドを使用してユーザーを検索します。

:snowflake:else @books = Book.looks(params[:search], params[:word])
検索範囲が"User"以外("Book")なら、同様にBookモデルのlooksメソッドを使用して本を検索します。

:shamrock: views

:ear_of_rice: 検索フォーム

:star: 部分テンプレートを作成して検索フォームを作成します。
_search.html.erb

<% if user_signed_in? %>
 <div class="search_form">
   <%= form_with url: search_result_path, method: :get, local: true do |f| %>
   <%= f.text_field :word %>
   <%= f.select :range, options_for_select([['User'],['Book']]) %>
   <%= f.select :search, options_for_select([["完全一致","perfect_match"],["前方一致","forward_match"],["後方一致","backward_match"],["部分一致","purtial_match"]]) %>
   <%= f.submit "検索", class: "btn btn-primary" %>
   <% end %>
 </div>
<% end %>

:snowflake:<% if user_signed_in? %> :ユーザーがログインしているか確認

:snowflake:<%= form_with url: search_result_path, method: :get, local: true do |f| %>
新たなフォームを作成します。このフォームはsearch_result_pathというURLにデータを送信します。
メソッドはGET、JavaScriptを使用せずに直接HTMLとして送信する設定(local: true)です。

:snowflake:<%= f.text_field :word %>: 検索フィールド表示

:snowflake:<%= f.select :range, options_for_select([['User'],['Book']]) %>
ドロップダウンリストを作成します。"User"または"Book"を選択できます。

:snowflake:同じように(完全一致、前方一致、後方一致、部分一致)ドロップダウンリストを作成。
(例: "完全一致")がユーザーに表示されるテキストで、2つ目の要素(例:"perfect_match")が実際の値(formが送信された時にサーバーに送られる値)です。

:star:検索フォームを好きなページに呼び出す

 <%= render 'books/search' %>

:corn: 完成イメージ
スクリーンショット 2023-07-09 17.59.47.png


:blossom: 検索結果ページ

searchsディレクトリ内にsearch_result.html.erbを作成

<h2>Book search for "test"</h2>

<table class="table table-hover table-inverse">
  <thead>
    <tr>
      <% if @range == "User" %>
        <th>Image</th>
        <th>Name</th>
      <% else %>
        <th>Image</th>
        <th>Title</th>
        <th>Opinion</th>
      <% end %>
      <th colspan="3"></th>
    </tr>
  </thead>
    
  <% if @range == "User" %>
    <!-- Userが検索対象の時 -->
    <tbody>
      <% @users.each do |user| %>
        <tr>
          <td><%= image_tag user.get_profile_image(50,50) %></td>
          <td><%= user.name %></td>
        </tr>
      <% end %>
    </tbody>
  <% else %>  
    <!-- User以外のモデル(Book)が検索対象の時 -->
    <tbody>
      <% @books.each do |book| %>
        <tr>
          <td><%= image_tag book.user.get_profile_image(50,50) %></td>
          <td><%= book.title %></td>
          <td><%= book.body %></td>
        </tr>
      <% end %>
    </tbody>
  <% end %>
</table>

:snowflake:userを検索した時には、プロフィール画像・名前を表示します。
userでない時(book)の時は、プロフィール画像・タイトル・内容を表示する。

:point_up: tableタグ解説
Userが検索対象の場合、タグ内に'Image'と'Name'を表示し、User以外(Book)が検索対象の場合、'Image', 'Title', 'Opinion'を表示します。

:corn: 完成イメージ スクリーンショット 2023-07-09 18.03.26.png


:hatching_chick: ひとこと
ご覧いただきありがとうございます!
一覧ページ等のレイアウト簡単なものなのでもう少し整えてみたいですね。
初心者ですので、間違った部分ありましたら教えてくださいね!

:cherry_blossom: 参考

https://qiita.com/hapiblog2020/items/6c2cef49df5616da9ae3

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?