##検索機能の実装
今回はよくある検索バーの実装を行う。その際にransack
と言うgemを使う。
ransack
が提供する検索フォームにはシンプルモード
とアドバンスモード
がある。
アドバンスモード
は入れ子になったAND/OR検索など、かなり複雑なことが実現できるが、今回は基本的な利用が目的なのでシンプルモードで実装を行う。
手順
①ransack
のインストール
②コントローラーの編集
③viewの実装
##①ransack
のインストール
Gemfileに以下のコードを記入後、bundle install
。
gem 'ransack'
##②コントローラーの編集
掲示板に検索機能を追加する場合、以下のようにコントローラーの編集を行う。
#このよくある1文を下記2行に変換
@boards = Board.all.includes(:user).order(created_at: :desc).page(params[:page])
↓↓
def index
@q = Board.ransack(params[:q])
@boards = @q.result(distinct: true).includes(:user).page(params[:page]).order("created_at desc")
end
params[:q]
には検索パラメータが渡され、result
により検索結果を得られる。
(distinct: true)
は記載しなくても使えるが、例えば絞り込み要件が「xxxというコメントがついている掲示板を取得する」場合にdistinct: true
がないと結果がおかしくなる。
掲示板Aに対して「ruby1」というコメントと「ruby2」というコメントがあったとし、この(distinct: true)
を入れなかったとき、ruby
でコメントを検索した場合に、掲示板Aが2回取得されて検索結果が2件になってしまうからである。
##③viewの実装
検索フォームはよく使われるので、パーシャルテンプレートとして作成。
search_form_for
というransack
が提供するフォームヘルパーを使ってフォームを作成。
#views/boards/_search.html.rb
<%= search_form_for @q, url: url do |f| %>
<%= f.search_field :title_or_body_cont, class: 'form-control', placeholder: '検索ワード' %>
<%= f.submit '検索', class: 'btn btn-primary' %>
<% end %>
#index.html.rb
<%= render 'search', q: @q, url: boards_path %>
・url: url
と記入することで、どこからでも呼び出せる汎用性の高いパーシャルファイルになる。
例えば、すべての掲示板から検索したい場合は、url: boards_path
とrender
に記載。ブックマークしている掲示板から検索したい場合は、url: bookmarks_boards_path
と記載…と言う風になる。
・title_or_body_cont
はそのカラムのtitleとbodyに検索した情報を含むレコード全てを取得する。
##ransackのよく使う述語(predicate)
述語(predicate)とは、先程boards
のtitleとbody
を絞り込み検索する際に、title_or_body_cont
と表記したが、この_cont
の部分が述語(predicate)に該当する。複数検索を導入する際にはtitle_or_body_cont
にもある通り、_or
を挟む。
*にはカラムを代入。
述語 | 意味(英語) | 意味 |
---|---|---|
*_eq | equal | 等しい |
*_not_eq | not equal | 等しくない |
*_lt | less than | より小さい |
*_lteq | less than or equal | より小さい(等しいものも含む) |
*_gt | grater than | より大きい |
*_gteq | grater than or equal | より大きい(等しいものも含む) |
*_cont | contains value | 部分一致(内容を含む) |
##選択による検索
下の図のように性別をボタンで選択し検索もできる。
<%= search_form_for @q do |f| %>
<%= f.label :sex %>
<%= f.radio_button :sex_eq, '', {:checked => true} %>指定なし
<%= f.radio_button :sex_eq, 1 %>男性
<%= f.radio_button :sex_eq, 2 %>女性
<%= f.submit "検索" %>
<% end %>
sex_eq
によって選んだものと数字の1,2が一致しているかどうかを検索。
##ソート機能
またransackには表示している情報を昇順降順で並び替える機能も備わっている。
<tr>
<th>Name</th>
<th>Age</th>
<th>Sex</th>
<th>Address</th>
</tr>
↓以下のように変換すると、ソート機能が使える
<tr>
<th><%= sort_link(@q, :name, "Name") %></th>
<th><%= sort_link(@q, :age, "Age") %></th>
<th><%= sort_link(@q, :sex, "Sex") %></th>
<th><%= sort_link(@q, :address, "Address") %></th>
</tr>
##参考記事
【Rails】ransackの使い方をざっくりまとめてみた
Rubyon Rails で検索機能を作ろう(ransack)
Ransackで簡単に検索フォームを作る73のレシピ