Railsにて検索機能を実装　（全体一致や部分一致などのselectボックスを入れ、複数モデルからの検索を可能にする）

備忘録として、なるべく自分の理解している範囲で、考え方の順序なども記載していく。

railsを触って、数週間なので、初心者の人のために

慣れている人や頭のいい人だと、そんなのわかってるよと言われることまで書いていきます。

間違っていたら教えてください。

devise でログイン機能は追加しており

UserモデルとBookモデルを作っています。


検索フォームをログインしている場合、全てのページに表示させたいので


app/views/layouts/application.html.erb  のviewに記載していく。


```

<% if user_signed_in? %>
       
   <%= form_tag(search_path, method: :get) do %>
    
　　<%= select_tag 'range' ,options_for_select([['---選択してください---', ''], ['User', '1'], ['Book', '2']]) %>

   　　<%= select_tag 'search', options_for_select([["前方一致","forward_match"], ["後方一致","backward_match"], ["完全一致","perfect_match"], ["部分一致","partial_match"]]) %>
   　　<%= text_field_tag (:word) %>
   　　<%= submit_tag "検索" %>

   <% end %>
          
<% end %>
```





全体を
<%= form_tag(search_path, method: :get) do %> と <% end %>でくくって

searchアクションにparamsである'range', 'search',(:word)を飛ばす 

```
<%= select_tag 'range' ,options_for_select([['---選択してください---', ''], ['User', '1'], ['Book', '2']]) %>
```

これの意味は['User', '1']この[ ]の中のUserを選んだ場合（ドロップダウンリスト）

’１’を'range'というparamsに入れて、コントローラに飛ばすために書いた。

```
<%= select_tag 'search', options_for_select([["前方一致","forward_match"], ["後方一致","backward_match"], ["完全一致","perfect_match"], ["部分一致","partial_match"]]) %>
```

これも同様にドロップダウンリストで選べるようにしているのですが

"前方一致"を選んだら"forward_match"を'search'というparamsに入れてsearchコントローラに飛ばすために書いた。

この２つのコードはselectボックスを作るために

select_tag 'paramsを決めてここに書く', options_for_select

params名はなんでも良い。

```
<%= text_field_tag (:word) %>
```

これは検索フォームに入力したワードをwordというparamsに入れて上と同様にsearchコントローラに飛ばすために書いた。

つまり３つのparamsをsearchコントローラに飛ばすコードを書いた。


![2020-03-23 18.24のイメージ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584558/6b2b2aa8-63b0-b2d7-f888-033279f4c931.jpeg)

こんな感じのができる。


続いてsearchesコントローラを書いていく

```
　 class SearchesController < ApplicationController
  
   　　def search
   　　　 @range = params[:range]
    　　　search = params[:search]
    　　　word = params[:word]

　　　　  if @range == '1'
          @user = User.search(search,word)
 　　　　 else
    　　　 @book = Book.search(search,word)
　　　　  end
　　　  end
  end
```

viewページから飛ばした３つのparamsをそれぞれインスタンス変数かローカル変数の中に入れるために

``` 
@range = params[:range]
search = params[:search]
word = params[:word]
```
を書いた。

searchとwordをローカル変数にしたのはmodelのメソッド（今回だとUserモデルとBookモデル）で利用するため、インスタンス変数じゃなくていいから。

```
　　　　if @range == '1'
　　　　  @user = User.search(search,word)
       else
    　　　@book = Book.search(search,word)
       end
```
１をユーザーが選んだ場合、
@userをviewページで反映させ、２を選んだら@bookを反映させる条件分岐。

ここで.search(search,word)という　searchメソッドを定義しなければいけない。

これはモデルで定義していく。



モデルについて

以下がモデルに検索のメソッドを定義する部分です。

ドロップダウンリストでUserを選んだ場合、

Userモデルにsearchメソッドを書いて、それをsearchコントローラーで呼べるようにする。



app/models/user.rb

```
    
def self.search(search,word)
		　　if search == "forward_match"
						　　　@user = User.where("name LIKE?","#{word}%")
		　　elsif search == "backward_match"
						　　　@user = User.where("name LIKE?","%#{word}")
		　　elsif search == "perfect_match"
						　　　@user = User.where("#{word}")
		　　elsif search == "partial_match"
						　　　@user = User.where("name LIKE?","%#{word}%")
		　　else
						　　　@user = User.all
		   end
  end

```

この書き方はググって出てきたものを真似した。

注意点は自分で定義した(search,word)２つのparamsを書くこと

searchにはviewページに書いた

"forward_match"や"backward_match"が入ってきている。

wordにはユーザーが検索フォームに入れたワードが入っている。


User.where("name LIKE?","#{word}%")

このコードはUserモデルから検索ワードにヒットしているかを確認するコードで


nameはUserテーブルのカラム名を記載する。

名前での検索だと思うのでnameにしてある



続いて、ユーザーBookを選んだ場合のメソッドをBookモデルに書いていく

```

def self.search(search, word)
		if search == "forward_match"
						@book = Book.where("title LIKE?","#{word}%")
		elsif search == "backward_match"
						@book = Book.where("title LIKE?","%#{word}")
		elsif search == "perfect_match"
						@book = Book.where("#{word}")
		elsif search == "partial_match"
						@book = Book.where("title LIKE?","%#{word}%")
		else
						@book = Book.all
		end
end

```
Userモデルと同様の書き方にする



そして検索結果を表示するviewページを作成

今回はsearchesフォルダにsearch.index.html.erbを作成したので

routes.rbに

```
get 'search' => 'searches#search'
```

を追記した。

続いて

search.html.erbには

```
<h2>Results index</h2>
<!--books一覧 -->
<table class="table table-hover table-inverse">
　<% if @range == '2' %>
  <thead>
    <tr>
     <th></th>
     <th>Title</th>
     <th>Opinion</th>
     <th colspan="3"></th>
    </tr>
  </thead>
  
  
  <tbody>
     <% @book.each do |book| %>
     <tr>
      <td>
	   <%= link_to(book.user) do %>
	   <%= attachment_image_tag(book.user, :profile_image, :fill, 50, 50, fallback: "no-image-mini.jpg") %>
       <% end %>
      </td>
      <td>
       <%= link_to book.title, book, class: "book_#{book.id}" %> 
      </td>
      <td><%= book.body %></td>
     </tr>
     <% end %>
  </tbody>

  <% else %>
  <thead>
     <tr>
      <th>image</th>
      <th>name</th>
      <th colspan="3"></th>
     </tr>
   </thead>
         
   <tbody>
    <% @user.each do |user| %>
     <tr>
      <td><%= attachment_image_tag(user, :profile_image, :fill, 50, 50, fallback: "no-image-mini.jpg") %></td>
      <td><%= user.name%></td>
      <td><%= link_to "Show", user, class: "user_#{user.id}" %></td>
     </tr>
    <% end %>
   </tbody>
   <% end %>
 </table>

```



終わりに
以上が検索機能の実装方法になります。
疑問、気になるところがございましたら、質問、コメントよろしくお願いします！！！