Railsにてransackというgemを使用して投稿一覧にて検索機能を作成。備忘録として記述。
検索機能を使わない場合は公開中の全投稿を表示、検索機能を使用した場合は検索結果を表示していきます。
フォロー機能も実装しているので、今回は、「都道府県」「ジャンル」「フォローしている人かどうか」で検索できるようにしていきます。
※新規投稿する際に都道府県、ジャンル、投稿の公開・非公開を選択して投稿する仕様にしています。(都道府県、ジャンル、投稿の公開・非公開はenumにて管理)
・都道府県
enum prefecture: {
hokkaido: 0,
aomori: 1,
~~~~~~~~~~~~ 省略 ~~~~~~~~~
kagoshima: 45,
okinawa: 46,
}
・ジャンル
enum location_genre: { food: 0, location: 1 }
・投稿の公開・非公開
enum released_flag: { released: 0, not_released: 1 }
①ransackのインストール
Gemfileに下記記述。
gem 'ransack'
インストールする。
bundle install
②コントローラーにメソッド記述。
def index
if params[:follow].present?
@follow = params[:follow]
else
@follow = false
end
@q = Post.ransack(params[:q])
@user = current_user.followings
@posts = @q.result(distinct: true).released.order(created_at: :desc).page(params[:page])
if @follow == 'true'
@posts = @q.result(distinct: true).where(user: @user).released.order(created_at: :desc).page(params[:page])
end
end
順を追って解説していくと、
(1)下記の記述については、もしパラメーターにfollowが存在していれば@followにパラメーターのfollowを定義。
もし存在していなければfalseを定義。
if params[:follow].present?
@follow = params[:follow]
else
@follow = false
end
(2)下記の記述については、
@q→Postの中から検索した情報をパラメーター(:q)に入れる。
@user→現在ログインしているユーザーがフォローしている人を定義。
@posts→@qの中から公開中(released)のものを検索して表示。(公開中の投稿を全表示)
distinct: true→重複を削除。
order(created_at: desc)→投稿を降順に表示。
@q = Post.ransack(params[:q])
@user = current_user.followings
@posts = @q.result(distinct: true).released.order(created_at: :desc)
(3)下記の記述については、
①で定義した@followがtrueの場合に、ログインユーザーがフォローしている人(current_user.id.followings)かつ公開中(released)の投稿を表示。
if @follow == 'true'
@posts = @q.result(distinct: true).where(user: @user).released.order(created_at: :desc)
end
③モデルに記述。
「検索可能な列」や「検索可能な関連モデル」をモデル内に予め定義しておく必要がある。
※悪意のあるユーザーが任意の検索条件を実行して、内部データを推測するセキュリティ問題を回避するため
def self.ransackable_attributes(auth_object = nil)
["address", "created_at", "id", "latitude", "location_genre", "location_name", "longitude","memo", "prefecture", "updated_at", "user_id"]
end
def self.ransackable_associations(auth_object = nil)
["favorites", "image_attachment", "image_blob", "notifications", "user"]
end
④viewに記述
フォロー済みユーザーを検索するかどうかは、チェックボックスへのチェックの有無にて判断するように実装。
検索ボタンは画像にて表示できるようにしました。
<%= search_form_for @q, url: posts_path, id: 'search_form' do |f| %>
<%= f.select :prefecture_eq, Post.prefectures_i18n.invert.map{|key, value| [key, Post.prefectures[value]]},
{ include_blank: t('--都道府県--') } %>
<%= f.select :location_genre_eq, Post.location_genres_i18n.invert.map{|key, value| [key, Post.location_genres[value]]},
{ include_blank: t('--ジャンル--') } %>
<%= label :follow, "フォロー済みユーザー" %>
<%= check_box_tag :follow, true, @follow %>
<%= image_submit_tag('検索ボタンの画像', width: "75px", height: "auto", class: "mx-1") %>
<% end %>