20
30

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 3 years have passed since last update.

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

Last updated at Posted at 2020-03-23

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

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を選んだ場合(ドロップダウンリスト)

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

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

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

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

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

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

params名はなんでも良い。

<%= text_field_tag (:word) %>

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

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

2020-03-23 18.24のイメージ.jpg

こんな感じのができる。

続いて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ページから飛ばした3つの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

1をユーザーが選んだ場合、
@userをviewページで反映させ、2を選んだら@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)2つの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>

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

20
30
3

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
20
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?