検索機能

### :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``
```diff_html
<% 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:検索フォームを好きなページに呼び出す
```diff_html
 <%= render 'books/search' %>
```

:corn: *完成イメージ*
![スクリーンショット 2023-07-09 17.59.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492906/135b0bc5-9a08-3d65-b3f4-6188cc23bbbe.png)

___
### :blossom: 検索結果ページ
searchsディレクトリ内に``search_result.html.erb``を作成
```diff_html
<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が検索対象の場合、<thead>タグ内に'Image'と'Name'を表示し、User以外（Book）が検索対象の場合、'Image', 'Title', 'Opinion'を表示します。


:corn: *完成イメージ* ![スクリーンショット 2023-07-09 18.03.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492906/aa76d0a6-0a50-d9cf-8ddd-94776d16b5e2.png)
____
:hatching_chick: **ひとこと**
ご覧いただきありがとうございます！
一覧ページ等のレイアウト簡単なものなのでもう少し整えてみたいですね。
初心者ですので、間違った部分ありましたら教えてくださいね！

### :cherry_blossom: 参考


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