1
2

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

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

Posted at

実装する内容

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

実装

今回はモデルを作らないため、コントローラとviewだけ作成
rails g controller Seraches searchをコマンドで実施。
get 'users/search' => 'searches#search'routes.rbに追加

まず初めに検索フォームを設置する。

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 %>

次にコントローラを実装

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に格納される

検索結果を表示させる

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なしでも簡単に実装できると思います。
何か抜けている部分やわからない所があればコメントお願いします。

1
2
0

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
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?