##検索機能の実装(ransack)
したいこと
投稿の一覧ページ(services_index)に検索機能の追加
サービス名、エリア名、カテゴリーでの検索
いいねの多い順、投稿順での並び替え
環境
Rails 5.2.4.4
前提
service.rb
belongs_to :user
belongs_to :category
has_many :likes
category.rb
has_many :services
like.rb
belongs_to :user
belongs_to :service
###手順
gemの追加
Gemfile
gem 'ransack'
追加したらbundle install
controllerの変更
services_controller.rb
def index
#省略
@categories = Category.all
# 検索フォームからアクセスした時の処理
if params[:q].present?
@search = Service.ransack(search_params)
@q = Service.ransack(params[:q])
@services = @q.result(distinct: true)
@services = @q.result.page(params[:page]).per(9)
# 検索フォーム以外からアクセスした時の処理
else
params[:q] = { sorts: 'id desc' }
@search = Service.ransack()
@services = Service.all.page(params[:page]).per(9)
end
end
#省略
private
#省略
def search_params
params.require(:q).permit(:name, :category_id, :area, :price, :introduction, :user_id, :image)
end
end
viewの変更
services/index.html.erb
<!-- 省略 -->
<%= search_form_for @search, url: services_path do |f| %>
<%= f.label :name, "サービス名" %>
<!-- "name_cont"はnameカラムの単語の一部分を含むものを検索するという意味 -->
<%= f.search_field :"name_cont" %>
<%= f.label :area, "対応エリア" %>
<%= f.search_field :"area_cont" %>
<%= f.label :category_id, "カテゴリー" %>
<%= f.collection_select :category_id_eq, @categories, :id, :name %>
<%= f.label :category_id, "並べ替え" %>
<%= f.select( :sorts, { '指定しない': 'id desc', 'いいねの多い順': 'likes_count desc', '出品の古い順': 'updated_at asc', '出品の新しい順': 'updated_at desc' } , { selected: params[:q][:sorts] }) %>
<%= f.submit "検索" %>
<% end %>
いいねの多い順での並び替えにはransackerを使い
検索機能を拡張しないといけないみたいなのでモデルに以下を追記
これでlikes_count
という条件でいいねの多い順に並び替えできるようにする
app/models/service.rb
#省略
ransacker :likes_count do
query = '(SELECT COUNT(likes.service_id) FROM likes where likes.service_id = services.id GROUP BY likes.service_id)'
Arel.sql(query)
end
これで検索機能といいね順、投稿順の並べ替えができました!