rails 検索機能　簡易的に

# railsでform_withを使用した検索機能を作ってみよう

railsの検索機能の記事はたくさんあるのですが、どれもform_tagでの実装であるので今回はrails 5.2.4~向けのform_withを使用して実装をしようかと思います。
複数のモデルでの条件分岐や,一致条件での条件分岐もおこなっています

# バージョン
 - ruby 2.6.3
 - rails 5.2.4
 - bootstrap 4.2.5

# 実装イメージ

![スクリーンショット 2021-07-13 18.49.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618242/29ed3378-e166-726a-3412-884dc5890076.png)

# 検索に必要なファイルやモデルを作成
- ターミナルで下記を作成
- 
    rails g model モデル名
    rails g controller books index
    rails g controller searchs top

# ルーティング設定
```ruby:routes.rb
resourecs: books,only: :index
get 'searchs/about', to: "searchs#top" ,as: search

```

# 検索機能のコードを作成

```ruby:books/index.html.erb
<%= form_with(url: search_path,method: :get,local: true) do |f| %>
    <%= f.text_field :search %>
    <%= f.select :model , options_for_select({User: :user,Book: :book })%>
    <%= f.select :how , options_for_select({完全一致: :"0",前方一致: :"1",後方一致: :"2",部分一致: :"3" })%>
    <%= f.submit 'Search'%>
<% end %>
```
## 上記のコードの説明

    <%= form_with(url: search_path,method: :get,local: true) do |f| %>
    # 検索結果を表示したいurlの指定します.

    <%= f.text_field :search %>
    # 検索するワードを searchという架空のカラムに格納される

    <%#= f.select :model , options_for_select({User: :user,Book: :book })%>
    #　検索したモデルをセレクトで選択でき,接頭文字が大文字の方が表示されるもの、接頭文字が小文字のものがmodelと言う架空のカラムに格納される
  

    <%#= f.select :how , options_for_select({完全一致: :"0",前方一致: :"1",後方一致: :"2",部分一致: :"3" })%>
    # 検索する際の条件のセレクトで選択した条件によってhowと言う架空のカラムに0~3のいづれかが格納される

# コントローラーのアクション設定
```ruby:searchs_controller.rb
  def top
    if params[:search].present?
			if params[:model] == "user"
				if params[:how] == "0"
					@users =User.where("name LIKE ?", "#{params[:search]}")
				elsif params[:how] == "1"
					@users =User.where("name LIKE ?", "#{params[:search]}%")
				elsif params[:how] == "2"
					@users =User.where("name LIKE ?", "%#{params[:search]}")
				else
					@users = User.where(['name LIKE ?', "%#{params[:search]}%"])
				end
			elsif params[:model] == "book"
				if params[:how] == "0"
					@books =Book.where("title LIKE ?", "#{params[:search]}")
				elsif params[:how] == "1"
					@books =Book.where("title LIKE ?", "#{params[:search]}%")
				elsif params[:how] == "2"
					@books =Book.where("title LIKE ?", "%#{params[:search]}")
				else
					@books = Book.where(['title LIKE ?', "%#{params[:search]}%"])
				end
			end
		end
  end
```

viewページで設定した架空のカラムでの条件分岐が大事です！
最初の1行では値格納されているかの確認をします
params[:model]でmodelに格納した値をの中身でuserモデルかbookモデルかの条件分岐を行います
params[:how]で一致する条件完全一致なのか,前半一致なのかなどの条件分岐を行います
それぞれ条件がととなった際に値を変数に入れviewページで表示させています


# 検索結果の表示
``` ruby:search.top.html
<% if params[:search].present? %>
    <% if params[:model] == "user" %>
	    <% @users.each do |f| %>
             <%= f.name %>
         <% end %>
    <% elsif params[:model] == "book"%>
	     <% @books.each do |f| %>
             <%= f.title %>
         <% end %>
    <% end %>
<% else %>
 検索結果は存在ません
<% end %>

``` 


### これでうまくいくと思いますwww


#### ちなみに綺麗にするならモデルにメソッドを作りましょう
```ruby:user.rb
def self.search(how,value)
    if how == "0"
      @users =User.where("name LIKE ?", "#{value}")
    elsif how == "1"
      @users =User.where("name LIKE ?", "#{value}%")
    elsif how == "2"
      @users =User.where("name LIKE ?", "%#{value}")
    else
      @users = User.where(['name LIKE ?', "%#{value}%"])
    end
  end
```

```ruby:book.rb
def self.search(how,value)
	if how == "0"
		@books =Book.where("title LIKE ?", "#{value}")
	elsif how == "1"
		@books =Book.where("title LIKE ?", "#{value}%")
	elsif how == "2"
		@books =Book.where("title LIKE ?", "%#{value}")
	else
		@books = Book.where(['title LIKE ?', "%#{value}%"])
	end
end
```

``` ruby:searchs_controller.rb
def top
	if params[:search].present?
		if params[:model] == "user"
		  @users =User.search(params[:how],params[:search])
		elsif params[:model] == "book"
		  @books =Book.search(params[:how],params[:search])
		end
	end
end
```

こちらの方がスッキリですね！

## 参考文献
https://qiita.com/rised/items/3d4cffe82ac46ee445ea 
https://qiita.com/Yusuke_Hoirta/items/159e63bcc5e99958d698