実装する内容
検索フォームに検索したいモデル二つと完全一致、前方一致、後方一致、部分一致のプルダウン式の条件選択を実装する。
(参考画像)http://drive.google.com/uc?export=view&id=1vsAOuXvOIV1IzDxaPhUJ0rLL0V0AgPUC
実装
今回はモデルを作らないため、コントローラとviewだけ作成
rails g controller Seraches searchをコマンドで実施。
get 'users/search' => 'searches#search'をroutes.rbに追加
まず初めに検索フォームを設置する。
<%= 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 %>
次にコントローラを実装
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に格納される
検索結果を表示させる
<% 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なしでも簡単に実装できると思います。
何か抜けている部分やわからない所があればコメントお願いします。
