基礎編19

2021.4.3

掲示板の検索機能を実装

ransackを使用して、掲示板の検索機能を実装する

 

参照

ransackを使った検索機能の実装 - Qiita

Ransackを使って検索機能を実装してみた - プログラミング学習 備忘録

【Rails】検索機能の実装手順 | たみずブログ

 

<ポイント>

① 検索フォームでurlを指定しないと、ブックマーク一覧の検索フォームでリクエストするurlが/boadsになってしまうので気をつける。

これだとBoardsController#indexにルーティングされてしまう。

②search_field :title_or_body_cont

タイトル(title)と本文(body)カラムに対して、最後の_contでLIKE句( =あいまい検索ができる)を利用した部分一致検索ができるようにしている。

(app/views/boards/_search_form.html.erb)

<%= search_form_for @q, url: url do |f| %>①
<div class='input-group mb-3'>
<%= f.search_field :title_or_body_cont, placeholder: t('defaults.search_word')
, class: 'form-control' %>②
<div class='input-group-append'>
<%= f.submit value: "検索", class: 'btn btn-primary' %>
</div>
</div>
<% end %>

 

② distinct: true 

「関連する子テーブルの情報を条件に絞り込んで、親テーブルの検索結果を表示するとき」に使用する

ex)「〇〇○というコメントがついている掲示板を取得する」場合にdistinct: true がないとおかしくなる

掲示板Aに対して「〇〇○が好き」「〇〇○は楽しい」というコメントがあった時

distinct: true がないと、「〇〇○」を検索した場合に掲示板Aが2回取得されて検索結果が2件になってしまう。

→なぜ起こるのか...

関連するテーブルをjoinすると一つの掲示板につきコメントの数だけ行が出来てしまう。これらを検索するとどちらの行も該当するので「掲示板A」の情報が2件取得される。distinct: true を使用して重複を取り除く

id   title      body  id  board_id     body

 掲示板 A     ▲▲▲  1                  〇〇○が好き

 掲示板 A     ▲▲▲  1                  〇〇○は楽しい

 

メソッドについて

参照

【Rails】ransackを使って検索機能がついたアプリを作ろう! | Pikawaka - ピカ1わかりやすいプログラミング用語サイト

def index
@q = Board.ransack(params[:q])
@boards = @q.result(distinct: true).includes(:user).order(created_at: :desc).page(params[:page])
end

 params[:q] : viewファイルから送られてくるパラメータ

ransackメソッド :送られてきたパラメータを元にテーブルからデータを検索するメソッド。(whereメソッドのransack版みたいな)

resultメソッド :ransackメソッドで取得したデータをActiveRecord_Relationのオブジェクトに変換するメソッド

 

<流れ>

❶ コントローラーを修正

(app/controllers/boards_controller.rb)

class BoardsController < ApplicationController

def index
@q = Board.ransack(params[:q])
@boards = @q.result(distinct: true).includes(:user).order(created_at: :desc).page(params[:page])
end

def bookmarks
@q = current_user.bookmark_boards.ransack(params[:q])
@bookmark_boards = @q.result(distinct: true).includes(:user).order(created_at: :desc).page(params[:page])
end

 
end

 

@q = Board.ransack(params[:q])

の部分でransackというgemを利用してparamsで値を受け取っているが、この値が空である時はransackの機能でよしなに全件取得する。検索ランが空白の時は検索ボタンを押しても全件表示される。

 

❷ 検索フォームを作成

(app/views/boards/_search_form.html.erb)

<%= search_form_for @q, url: url do |f| %>
<div class='input-group mb-3'>
<%= f.search_field :title_or_body_cont, placeholder: t('defaults.search_word')
, class: 'form-control' %>
<div class='input-group-append'>
<%= f.submit value: "検索", class: 'btn btn-primary' %>
</div>
</div>
<% end %>

 

❸ index.html と bookmarks.html.erb で呼び出す

ローカル変数に

q : 検索オブジェクト (今回は@qを省略)

url: リクエストするURL

(app/views/boards/index.html.erb)

<!-- 検索フォーム -->
<%= render 'search_form', url: boards_path %>

 

(app/views/boards/bookmarks.html.erb)

<%= render 'search_form', url: bookmarks_boards_path %>