Rails5 gemなしで複数モデルの絞り込み検索機能を実装する。

#実装する内容
検索フォームに検索したいモデル二つと完全一致、前方一致、後方一致、部分一致のプルダウン式の条件選択を実装する。
(参考画像）http://drive.google.com/uc?export=view&id=1vsAOuXvOIV1IzDxaPhUJ0rLL0V0AgPUC


<img src=https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F700999%2Fa126f999-9e5e-f80c-913d-e7ee2c86652a.gif?ixlib=rb-1.2.2&auto=format&gif-q=60&q=75&s=b85b97e43acfbe1b95ec86c20570bce4>



#実装
今回はモデルを作らないため、コントローラとviewだけ作成
`rails g controller Seraches search`をコマンドで実施。
`get 'users/search' => 'searches#search'`を`routes.rb`に追加
###まず初めに検索フォームを設置する。
```ruby:views/自分が検索フォームを入れたいview
<%= form_tag(users_search_path, method: :get) do %>
    <%= text_field_tag 'search[content]' %>
   	<%= select_tag 'search[model]', options_for_select({ "ユーザー" => "user", "タグ" => "muscle" }) %>
   	<%= select_tag 'search[how]', options_for_select({ "完全一致" => "match", "前方一致" => "forward", "後方一致" => "backward", "部分一致" => "partical"  }) %>
    <%= submit_tag '検索', class: "btn btn-primary" %>
  <% end %>
```
###次にコントローラを実装

```ruby:users/searches_controller.rb

def search
    @content = params['search']['content']
    @how = params['search']['how']
    @model = params['search']['model']
    @datas = search_for(@how, @model, @content)
end

private

  def match(model, content)
    if model == 'user'
      User.where(name: content)
    elsif model == 'muscle'
      Muscle.where(work_tag: content)
    end
  end

  def forward(model, content)
    if model == 'user'
      User.where('name LIKE ?', "#{content}%")
    elsif model == 'muscle'
      Muscle.where('work_tag LIKE ?', "#{content}%")
    end
  end

  def backward(model, content)
    if model == 'user'
      User.where('name LIKE ?', "%#{content}")
    elsif model == 'muscle'
      Muscle.where('work_tag LIKE ?', "%#{content}")
    end
  end

  def partical(model, content)
    if model == 'user'
      User.where('name LIKE ?', "%#{content}%")
    elsif model == 'muscle'
      Muscle.where('work_tag LIKE ?', "%#{content}%")
    end
  end

  def search_for(how, model, content)
    case how
    when 'match'
      match(model, content)
    when 'forward'
      forward(model, content)
    when 'backward'
      backward(model, content)
    when 'partical'
      partical(model, content)
    end
  end
end
```
###controllerの説明
自分はMusclesテーブルのwork_tagカラムとUsersテーブルのnameカラムを検索対象にしているのでそこは個人ごとで変更してください。

```
    @content = params['search']['content']
    @how = params['search']['how']
    @model = params['search']['model']
    @datas = search_for(@how, @model, @content)
```
###区切って解説
・まず初めにform_tagを設置しているviewからユーザーが検索を実行すると、searches_controllerが呼ばれて、@contentにviewから送られてきた検索内容を格納。
・@howにviewから送られてきた完全一致などの条件を格納
・@modelにviewから送られてきたユーザーなどの検索したいモデルを格納
・@datasにはsearch_forメソッドを発動し引数として(@how, @model, @content)を渡す。

### search_forをみていく
```
def search_for(how, model, content)
    case how
    when 'match'
      match(model, content)
    when 'forward'
      forward(model, content)
    when 'backward'
      backward(model, content)
    when 'partical'
      partical(model, content)
    end
end

```

・`'match'`はform_tagのところをみてもらうと分かるのだが完全一致、`'partcial'`は部分一致である。
・case文でhowの中身が`'match'である場合serach_forメソッドの中でさらにmatchメソッドを呼んでいる。
###matchメソッドをみていく
```
def match(model, content)
    if model == 'user'
      User.where(name: content)
    elsif model == 'muscle'
      Muscle.where(work_tag: content)
    end
  end
```
・呼ばれたmatchメソッドでは格納されているmodelの中身がuserかmuscleかで条件分岐している。
・もちろん完全一致なのでUserの場合だと`User.where`でフォームから送られてきたcontentとnameカラムが一致するもの全てを取得している
・これでmatchメソッドが実施されて、その結果が@datasに格納される
###検索結果を表示させる

```rails:views/seaches/searche.html.erb

<% if @model == "user" %>
<div class="row  justify-content-center">
  <h2>ユーザ 一覧</h2>
</div>
<div class="row  justify-content-center">
  <% @datas.each do |datas| %>
  <table class="table table-striped table-bordered">
   	<thead>
		<tr>
			<th>ユーザー名</th>
	        </tr>
       </thead>
   	<tbody>
	   	<tr>
	    	<td>
	    	  <%= link_to datas.name, user_path(datas.id) %>
	    	</td>
	    </tr>
	</tbody>
	</table>
	<% end %>
</div>

<% elsif @model == "muscle"%>
<div class="row  justify-content-center">
<table class="table table-striped table-bordered">
   	<thead>
		<tr>
			<th>タグ一覧</th>
	        </tr>
       </thead>
   	<tbody>
	   	<tr>
	    	<td>
	    		<%= link_to datas.work_tag, muscle_path(datas.id) %>
	    	</td>
	    </tr>
	</tbody>
	</table>
</div>
<% else %>
<% end %>

```
・if文でmodelがuserかmuscleかで表示させるhtmlを変える。
・@datasに格納された物をeach doで回して一覧で表示させる。

#最後に
メソッドさえ理解すればgemなしでも簡単に実装できると思います。
何か抜けている部分やわからない所があればコメントお願いします。